ReactOS  0.4.10-dev-244-gb941574
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 
236  Process, ProcessBasicInformation,
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  }
243  Status = NtReadVirtualMemoryPtr (
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 
281  hShExt = (MYEX)(FARPROC)GetProcAddress(hShell32, SHELLEXECUTETEXT);
282  if (!hShExt)
283  {
284  WARN ("RunFile: couldn't find ShellExecuteExA/W in SHELL32.DLL!\n");
285  FreeLibrary(hShell32);
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 
302  FreeLibrary(hShell32);
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;
388  if (!SetCurrentDirectory(first))
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 */
405  StripQuotes(First);
406  if (!SearchForExecutable(First, szFullName))
407  {
408  error_bad_command(first);
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 */
489  EnterCriticalSection(&ChildProcessRunningLock);
491 
493 
494  LeaveCriticalSection(&ChildProcessRunningLock);
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));
504  error_bad_command(first);
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 */
744  EnterCriticalSection(&ChildProcessRunningLock);
745  WaitForMultipleObjects(nProcesses, hProcess, TRUE, INFINITE);
746  LeaveCriticalSection(&ChildProcessRunningLock);
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 
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 
1499  ExecuteCommand(Cmd);
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 
1519  if (!TryEnterCriticalSection(&ChildProcessRunningLock))
1520  {
1521  /* Child process is running and will have received the control event */
1522  return TRUE;
1523  }
1524  else
1525  {
1526  LeaveCriticalSection(&ChildProcessRunningLock);
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)
1669  bDelayedExpansion = !!*(PDWORD)Buffer;
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)
1686  bEnableExtensions = !!*(PDWORD)Buffer;
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 */
1886  if (GetModuleFileName(NULL, ModuleName, ARRAYSIZE(ModuleName)) != 0)
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 
2075  DeleteCriticalSection(&ChildProcessRunningLock);
2076 }
2077 
2078 /*
2079  * main function
2080  */
2081 int _tmain(int argc, const TCHAR *argv[])
2082 {
2083  TCHAR startPath[MAX_PATH];
2084 
2085  InitializeCriticalSection(&ChildProcessRunningLock);
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
DWORD *typedef PVOID
Definition: winlogon.h:52
#define RegQueryValueEx
Definition: winreg.h:524
INT nErrorLevel
Definition: cmd.c:157
static VOID ProcessInput(VOID)
Definition: cmd.c:1486
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 const char UINT32 const char const char * ModuleName
Definition: acpixf.h:1256
VOID PrintCommandList(VOID)
Definition: cmdtable.c:242
INT FormatTime(TCHAR *, LPSYSTEMTIME)
Definition: dir.c:688
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
#define cmd_exit(code)
Definition: cmddbg.h:34
unsigned short WORD
Definition: ntddk_ex.h:93
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:130
WORD wVirtualScanCode
Definition: wincon.h:228
LPSTR lpTitle
Definition: winbase.h:799
#define SHELLEXECUTETEXT
Definition: cmd.c:260
struct _PARSED_COMMAND * Subcommands
Definition: cmd.h:301
#define ERROR_SUCCESS
Definition: deptool.c:10
VOID CleanHistory(VOID)
Definition: history.c:149
#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:1225
#define _tcstol
Definition: tchar.h:594
#define MAXIMUM_WAIT_OBJECTS
Definition: winbase.h:385
BYTE Type
Definition: cmd.h:304
#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
unsigned char * LPBYTE
Definition: typedefs.h:52
#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
INT cmd_date(LPTSTR)
Definition: date.c:176
VOID DestroyDirectoryStack(VOID)
Definition: dirstack.c:90
#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
#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:1056
$ULONG LowPart
Definition: ntbasedef.h:576
static VOID GetCmdLineCommand(TCHAR *commandline, TCHAR *ptr, BOOL AlwaysStrip)
Definition: cmd.c:1783
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:137
_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:659
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
_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 _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
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 _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
DWORD DWORD
Definition: winlogon.h:75
static char ** argv
Definition: ServiceArgs.c:11
struct _PARSED_COMMAND * Next
Definition: cmd.h:302
CHAR * LPTSTR
Definition: xmlstorage.h:192
struct TraceInfo Info
LPTSTR ReadBatchLine()
Definition: batch.c:446
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
NTSTATUS(WINAPI * NtQueryInformationProcessProc)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG)
Definition: cmd.c:148
TCHAR firstvar
Definition: batch.h:27
#define ENABLE_ECHO_INPUT
Definition: wincon.h:77
WCHAR First[]
Definition: FormatMessage.c:11
GLuint n
Definition: s_context.h:57
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
GLenum GLclampf GLint i
Definition: glfuncs.h:14
LPTSTR _stpcpy(LPTSTR, LPCTSTR)
Definition: misc.c:449
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
WORD wRepeatCount
Definition: wincon.h:226
#define StringCchPrintf
Definition: strsafe.h:517
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
#define FALSE
Definition: types.h:117
GLenum const GLfloat * params
Definition: glext.h:5645
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:852
#define _MAX_PATH
Definition: utility.h:77
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, BOOL Add)
Definition: console.c:2111
NTSTATUS(WINAPI * NtReadVirtualMemoryProc)(HANDLE, PVOID, PVOID, ULONG, PULONG)
Definition: cmd.c:150
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
#define INT(a)
Definition: assyntax.h:463
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
#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
#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
UINTN Size
Definition: acefiex.h:555
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
$ULONG HighPart
Definition: ntbasedef.h:577
BOOL WINAPI FileTimeToSystemTime(IN CONST FILETIME *lpFileTime, OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:178
unsigned int BOOL
Definition: ntddk_ex.h:94
INT ConvertULargeInteger(ULONGLONG num, LPTSTR des, UINT len, BOOL bPutSeparator)
Definition: cmd.c:188
GLsizeiptr size
Definition: glext.h:5919
LONG NTSTATUS
Definition: precomp.h:26
DWORD cb
Definition: winbase.h:796
#define STRING_CMD_HELP4
Definition: resource.h:79
VOID InitDirectoryStack(VOID)
Definition: dirstack.c:79
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:24
LPCSTR lpParameters
Definition: shellapi.h:312
HANDLE HKEY
Definition: registry.h:24
uint64_t ULONGLONG
Definition: typedefs.h:65
#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
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
TCHAR PathCompletionChar
Definition: cmdinput.c:112
LPTSTR DoDelayedExpansion(LPTSTR Line)
Definition: cmd.c:1408
#define ConOutResPrintf(uID,...)
Definition: console.h:48
HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] STATPROPSETSTG *rgelt, [out] ULONG *pceltFetched)
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
int(* FARPROC)()
Definition: compat.h:28
UINTN VOID * Buffer
Definition: acefiex.h:370
CON_STREAM_MODE OutputStreamMode
Definition: cmd.c:176
Definition: partlist.h:32
#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
union _INPUT_RECORD::@3132 Event
BOOL WINAPI TryEnterCriticalSection(LPCRITICAL_SECTION)
BOOL(WINAPI * MYEX)(LPSHELLEXECUTEINFO lpExecInfo)
Definition: cmd.c:263
Definition: sacdrv.h:278
#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
#define GetFullPathName
Definition: winbase.h:3635
PBYTE Character
Definition: device.h:83
VOID UndoRedirection(REDIRECTION *, REDIRECTION *End)
Definition: redir.c:142
GLenum GLsizei len
Definition: glext.h:6722
#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
static stack_node_t temp
Definition: rpn.c:18
VOID FreeCommand(PARSED_COMMAND *Cmd)
Definition: parser.c:955
#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
#define WINAPI
Definition: msvc.h:20
LPCSTR lpDirectory
Definition: shellapi.h:313
UINTN UINT8 Value
Definition: acefiex.h:751
TCHAR AutoCompletionChar
Definition: cmdinput.c:111
Definition: cmd.h:298
Status
Definition: gdiplustypes.h:24
struct _REDIRECTION * Redirections
Definition: cmd.h:303
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:854
union _KEY_EVENT_RECORD::@3131 uChar
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
DWORD *typedef HANDLE
Definition: winlogon.h:52
#define cmd_free(ptr)
Definition: cmddbg.h:31
#define TEXT(s)
Definition: k32.h:26
static const WCHAR des[]
Definition: oid.c:1049
#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
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:1589
#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
#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:717
#define STRING_FREE_ERROR1
Definition: resource.h:49
WORD EventType
Definition: wincon.h:261
HANDLE HMODULE
Definition: typedefs.h:75
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:58
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:458
#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
#define INFINITE
Definition: serial.h:102
#define memset(x, y, z)
Definition: compat.h:39
#define REG_DWORD
Definition: sdbapi.c:539
BOOL IsExistingFile(LPCTSTR)
Definition: misc.c:488
struct tagFORCONTEXT * prev
Definition: batch.h:26
#define BOOL
Definition: msvc.h:23
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 _tchdir(const _TCHAR *_path)
Definition: chdir.c:8
VOID PrintPrompt(VOID)
Definition: prompt.c:109
static BOOL Full
Definition: gflags.c:20
#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:308
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:1196
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
static VOID Initialize(VOID)
Definition: cmd.c:1839
struct _PARSED_COMMAND::@54::@56 Command
#define REG_SZ
Definition: layer.c:22
BOOL bCtrlBreak
Definition: cmd.c:154
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:500