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