ReactOS  0.4.9-dev-728-g3d012a4
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 INT
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 nErrorLevel;
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  return nErrorLevel;
726 }
727 
728 INT
730 {
731  PARSED_COMMAND *Sub;
732  LPTSTR First, Rest;
733  INT Ret = 0;
734 
735  if (!PerformRedirection(Cmd->Redirections))
736  return 1;
737 
738  switch (Cmd->Type)
739  {
740  case C_COMMAND:
741  Ret = 1;
742  First = DoDelayedExpansion(Cmd->Command.First);
743  if (First)
744  {
745  Rest = DoDelayedExpansion(Cmd->Command.Rest);
746  if (Rest)
747  {
748  Ret = DoCommand(First, Rest, Cmd);
749  cmd_free(Rest);
750  }
751  cmd_free(First);
752  }
753  break;
754  case C_QUIET:
755  case C_BLOCK:
756  case C_MULTI:
757  for (Sub = Cmd->Subcommands; Sub; Sub = Sub->Next)
758  Ret = ExecuteCommand(Sub);
759  break;
760  case C_IFFAILURE:
761  Sub = Cmd->Subcommands;
762  Ret = ExecuteCommand(Sub);
763  if (Ret != 0)
764  {
765  nErrorLevel = Ret;
766  Ret = ExecuteCommand(Sub->Next);
767  }
768  break;
769  case C_IFSUCCESS:
770  Sub = Cmd->Subcommands;
771  Ret = ExecuteCommand(Sub);
772  if (Ret == 0)
773  Ret = ExecuteCommand(Sub->Next);
774  break;
775  case C_PIPE:
776  Ret = ExecutePipeline(Cmd);
777  break;
778  case C_IF:
779  Ret = ExecuteIf(Cmd);
780  break;
781  case C_FOR:
782  Ret = ExecuteFor(Cmd);
783  break;
784  }
785 
787  return Ret;
788 }
789 
790 LPTSTR
792 {
793  static LPTSTR ret = NULL;
794  UINT size;
795 
796  cmd_free(ret);
797  ret = NULL;
798  size = GetEnvironmentVariable(varName, NULL, 0);
799  if (size > 0)
800  {
801  ret = cmd_alloc(size * sizeof(TCHAR));
802  if (ret != NULL)
803  GetEnvironmentVariable(varName, ret, size + 1);
804  }
805  return ret;
806 }
807 
808 LPCTSTR
810 {
811  static TCHAR ret[MAX_PATH];
812 
813  LPTSTR var = GetEnvVar(varName);
814  if (var)
815  return var;
816 
817  /* env var doesn't exist, look for a "special" one */
818  /* %CD% */
819  if (_tcsicmp(varName,_T("cd")) ==0)
820  {
822  return ret;
823  }
824  /* %TIME% */
825  else if (_tcsicmp(varName,_T("time")) ==0)
826  {
827  return GetTimeString();
828  }
829  /* %DATE% */
830  else if (_tcsicmp(varName,_T("date")) ==0)
831  {
832  return GetDateString();
833  }
834 
835  /* %RANDOM% */
836  else if (_tcsicmp(varName,_T("random")) ==0)
837  {
838  /* Get random number */
839  _itot(rand(),ret,10);
840  return ret;
841  }
842 
843  /* %CMDCMDLINE% */
844  else if (_tcsicmp(varName,_T("cmdcmdline")) ==0)
845  {
846  return GetCommandLine();
847  }
848 
849  /* %CMDEXTVERSION% */
850  else if (_tcsicmp(varName,_T("cmdextversion")) ==0)
851  {
852  /* Set version number to 2 */
853  _itot(2,ret,10);
854  return ret;
855  }
856 
857  /* %ERRORLEVEL% */
858  else if (_tcsicmp(varName,_T("errorlevel")) ==0)
859  {
860  _itot(nErrorLevel,ret,10);
861  return ret;
862  }
863 
864  return NULL;
865 }
866 
867 /* Handle the %~var syntax */
868 static LPTSTR
869 GetEnhancedVar(TCHAR **pFormat, LPTSTR (*GetVar)(TCHAR, BOOL *))
870 {
871  static const TCHAR ModifierTable[] = _T("dpnxfsatz");
872  enum {
873  M_DRIVE = 1, /* D: drive letter */
874  M_PATH = 2, /* P: path */
875  M_NAME = 4, /* N: filename */
876  M_EXT = 8, /* X: extension */
877  M_FULL = 16, /* F: full path (drive+path+name+ext) */
878  M_SHORT = 32, /* S: full path (drive+path+name+ext), use short names */
879  M_ATTR = 64, /* A: attributes */
880  M_TIME = 128, /* T: modification time */
881  M_SIZE = 256, /* Z: file size */
882  } Modifiers = 0;
883 
884  TCHAR *Format, *FormatEnd;
885  TCHAR *PathVarName = NULL;
886  LPTSTR Variable;
887  TCHAR *VarEnd;
888  BOOL VariableIsParam0;
889  TCHAR FullPath[MAX_PATH];
890  TCHAR FixedPath[MAX_PATH], *Filename, *Extension;
891  HANDLE hFind;
892  WIN32_FIND_DATA w32fd;
893  TCHAR *In, *Out;
894 
895  static TCHAR Result[CMDLINE_LENGTH];
896 
897  /* There is ambiguity between modifier characters and FOR variables;
898  * the rule that cmd uses is to pick the longest possible match.
899  * For example, if there is a %n variable, then out of %~anxnd,
900  * %~anxn will be substituted rather than just %~an. */
901 
902  /* First, go through as many modifier characters as possible */
903  FormatEnd = Format = *pFormat;
904  while (*FormatEnd && _tcschr(ModifierTable, _totlower(*FormatEnd)))
905  FormatEnd++;
906 
907  if (*FormatEnd == _T('$'))
908  {
909  /* $PATH: syntax */
910  PathVarName = FormatEnd + 1;
911  FormatEnd = _tcschr(PathVarName, _T(':'));
912  if (!FormatEnd)
913  return NULL;
914 
915  /* Must be immediately followed by the variable */
916  Variable = GetVar(*++FormatEnd, &VariableIsParam0);
917  if (!Variable)
918  return NULL;
919  }
920  else
921  {
922  /* Backtrack if necessary to get a variable name match */
923  while (!(Variable = GetVar(*FormatEnd, &VariableIsParam0)))
924  {
925  if (FormatEnd == Format)
926  return NULL;
927  FormatEnd--;
928  }
929  }
930 
931  for (; Format < FormatEnd && *Format != _T('$'); Format++)
932  Modifiers |= 1 << (_tcschr(ModifierTable, _totlower(*Format)) - ModifierTable);
933 
934  *pFormat = FormatEnd + 1;
935 
936  /* Exclude the leading and trailing quotes */
937  VarEnd = &Variable[_tcslen(Variable)];
938  if (*Variable == _T('"'))
939  {
940  Variable++;
941  if (VarEnd > Variable && VarEnd[-1] == _T('"'))
942  VarEnd--;
943  }
944 
945  if ((char *)VarEnd - (char *)Variable >= sizeof Result)
946  return _T("");
947  memcpy(Result, Variable, (char *)VarEnd - (char *)Variable);
948  Result[VarEnd - Variable] = _T('\0');
949 
950  if (PathVarName)
951  {
952  /* $PATH: syntax - search the directories listed in the
953  * specified environment variable for the file */
954  LPTSTR PathVar;
955  FormatEnd[-1] = _T('\0');
956  PathVar = GetEnvVar(PathVarName);
957  FormatEnd[-1] = _T(':');
958  if (!PathVar ||
959  !SearchPath(PathVar, Result, NULL, MAX_PATH, FullPath, NULL))
960  {
961  return _T("");
962  }
963  }
964  else if (Modifiers == 0)
965  {
966  /* For plain %~var with no modifiers, just return the variable without quotes */
967  return Result;
968  }
969  else if (VariableIsParam0)
970  {
971  /* Special case: If the variable is %0 and modifier characters are present,
972  * use the batch file's path (which includes the .bat/.cmd extension)
973  * rather than the actual %0 variable (which might not). */
974  _tcscpy(FullPath, bc->BatchFilePath);
975  }
976  else
977  {
978  /* Convert the variable, now without quotes, to a full path */
979  if (!GetFullPathName(Result, MAX_PATH, FullPath, NULL))
980  return _T("");
981  }
982 
983  /* Next step is to change the path to fix letter case (e.g.
984  * C:\ReAcToS -> C:\ReactOS) and, if requested with the S modifier,
985  * replace long filenames with short. */
986 
987  In = FullPath;
988  Out = FixedPath;
989 
990  /* Copy drive letter */
991  *Out++ = *In++;
992  *Out++ = *In++;
993  *Out++ = *In++;
994  /* Loop over each \-separated component in the path */
995  do {
996  TCHAR *Next = _tcschr(In, _T('\\'));
997  if (Next)
998  *Next++ = _T('\0');
999  /* Use FindFirstFile to get the correct name */
1000  if (Out + _tcslen(In) + 1 >= &FixedPath[MAX_PATH])
1001  return _T("");
1002  _tcscpy(Out, In);
1003  hFind = FindFirstFile(FixedPath, &w32fd);
1004  /* If it doesn't exist, just leave the name as it was given */
1005  if (hFind != INVALID_HANDLE_VALUE)
1006  {
1007  LPTSTR FixedComponent = w32fd.cFileName;
1008  if (*w32fd.cAlternateFileName &&
1009  ((Modifiers & M_SHORT) || !_tcsicmp(In, w32fd.cAlternateFileName)))
1010  {
1011  FixedComponent = w32fd.cAlternateFileName;
1012  }
1013  FindClose(hFind);
1014 
1015  if (Out + _tcslen(FixedComponent) + 1 >= &FixedPath[MAX_PATH])
1016  return _T("");
1017  _tcscpy(Out, FixedComponent);
1018  }
1019  Filename = Out;
1020  Out += _tcslen(Out);
1021  *Out++ = _T('\\');
1022 
1023  In = Next;
1024  } while (In != NULL);
1025  Out[-1] = _T('\0');
1026 
1027  /* Build the result string. Start with attributes, modification time, and
1028  * file size. If the file didn't exist, these fields will all be empty. */
1029  Out = Result;
1030  if (hFind != INVALID_HANDLE_VALUE)
1031  {
1032  if (Modifiers & M_ATTR)
1033  {
1034  static const struct {
1035  TCHAR Character;
1036  WORD Value;
1037  } *Attrib, Table[] = {
1038  { _T('d'), FILE_ATTRIBUTE_DIRECTORY },
1039  { _T('r'), FILE_ATTRIBUTE_READONLY },
1040  { _T('a'), FILE_ATTRIBUTE_ARCHIVE },
1041  { _T('h'), FILE_ATTRIBUTE_HIDDEN },
1042  { _T('s'), FILE_ATTRIBUTE_SYSTEM },
1043  { _T('c'), FILE_ATTRIBUTE_COMPRESSED },
1044  { _T('o'), FILE_ATTRIBUTE_OFFLINE },
1045  { _T('t'), FILE_ATTRIBUTE_TEMPORARY },
1046  { _T('l'), FILE_ATTRIBUTE_REPARSE_POINT },
1047  };
1048  for (Attrib = Table; Attrib != &Table[9]; Attrib++)
1049  {
1050  *Out++ = w32fd.dwFileAttributes & Attrib->Value
1051  ? Attrib->Character
1052  : _T('-');
1053  }
1054  *Out++ = _T(' ');
1055  }
1056  if (Modifiers & M_TIME)
1057  {
1058  FILETIME ft;
1059  SYSTEMTIME st;
1060  FileTimeToLocalFileTime(&w32fd.ftLastWriteTime, &ft);
1061  FileTimeToSystemTime(&ft, &st);
1062 
1063  Out += FormatDate(Out, &st, TRUE);
1064  *Out++ = _T(' ');
1065  Out += FormatTime(Out, &st);
1066  *Out++ = _T(' ');
1067  }
1068  if (Modifiers & M_SIZE)
1069  {
1071  Size.LowPart = w32fd.nFileSizeLow;
1072  Size.HighPart = w32fd.nFileSizeHigh;
1073  Out += _stprintf(Out, _T("%I64u "), Size.QuadPart);
1074  }
1075  }
1076 
1077  /* When using the path-searching syntax or the S modifier,
1078  * at least part of the file path is always included.
1079  * If none of the DPNX modifiers are present, include the full path */
1080  if (PathVarName || (Modifiers & M_SHORT))
1081  if ((Modifiers & (M_DRIVE | M_PATH | M_NAME | M_EXT)) == 0)
1082  Modifiers |= M_FULL;
1083 
1084  /* Now add the requested parts of the name.
1085  * With the F modifier, add all parts to form the full path. */
1086  Extension = _tcsrchr(Filename, _T('.'));
1087  if (Modifiers & (M_DRIVE | M_FULL))
1088  {
1089  *Out++ = FixedPath[0];
1090  *Out++ = FixedPath[1];
1091  }
1092  if (Modifiers & (M_PATH | M_FULL))
1093  {
1094  memcpy(Out, &FixedPath[2], (char *)Filename - (char *)&FixedPath[2]);
1095  Out += Filename - &FixedPath[2];
1096  }
1097  if (Modifiers & (M_NAME | M_FULL))
1098  {
1099  while (*Filename && Filename != Extension)
1100  *Out++ = *Filename++;
1101  }
1102  if (Modifiers & (M_EXT | M_FULL))
1103  {
1104  if (Extension)
1105  Out = _stpcpy(Out, Extension);
1106  }
1107 
1108  /* Trim trailing space which otherwise would appear as a
1109  * result of using the A/T/Z modifiers but no others. */
1110  while (Out != &Result[0] && Out[-1] == _T(' '))
1111  Out--;
1112  *Out = _T('\0');
1113 
1114  return Result;
1115 }
1116 
1117 LPCTSTR
1118 GetBatchVar(TCHAR *varName, UINT *varNameLen)
1119 {
1120  LPCTSTR ret;
1121  TCHAR *varNameEnd;
1122  BOOL dummy;
1123 
1124  *varNameLen = 1;
1125 
1126  switch ( *varName )
1127  {
1128  case _T('~'):
1129  varNameEnd = varName + 1;
1130  ret = GetEnhancedVar(&varNameEnd, FindArg);
1131  if (!ret)
1132  {
1133  error_syntax(varName);
1134  return NULL;
1135  }
1136  *varNameLen = varNameEnd - varName;
1137  return ret;
1138  case _T('0'):
1139  case _T('1'):
1140  case _T('2'):
1141  case _T('3'):
1142  case _T('4'):
1143  case _T('5'):
1144  case _T('6'):
1145  case _T('7'):
1146  case _T('8'):
1147  case _T('9'):
1148  return FindArg(*varName, &dummy);
1149 
1150  case _T('*'):
1151  //
1152  // Copy over the raw params(not including the batch file name
1153  //
1154  return bc->raw_params;
1155 
1156  case _T('%'):
1157  return _T("%");
1158  }
1159  return NULL;
1160 }
1161 
1162 BOOL
1163 SubstituteVars(TCHAR *Src, TCHAR *Dest, TCHAR Delim)
1164 {
1165 #define APPEND(From, Length) { \
1166  if (Dest + (Length) > DestEnd) \
1167  goto too_long; \
1168  memcpy(Dest, From, (Length) * sizeof(TCHAR)); \
1169  Dest += Length; }
1170 #define APPEND1(Char) { \
1171  if (Dest >= DestEnd) \
1172  goto too_long; \
1173  *Dest++ = Char; }
1174 
1175  TCHAR *DestEnd = Dest + CMDLINE_LENGTH - 1;
1176  const TCHAR *Var;
1177  int VarLength;
1178  TCHAR *SubstStart;
1179  TCHAR EndChr;
1180  while (*Src)
1181  {
1182  if (*Src != Delim)
1183  {
1184  APPEND1(*Src++)
1185  continue;
1186  }
1187 
1188  Src++;
1189  if (bc && Delim == _T('%'))
1190  {
1191  UINT NameLen;
1192  Var = GetBatchVar(Src, &NameLen);
1193  if (Var != NULL)
1194  {
1195  VarLength = _tcslen(Var);
1196  APPEND(Var, VarLength)
1197  Src += NameLen;
1198  continue;
1199  }
1200  }
1201 
1202  /* Find the end of the variable name. A colon (:) will usually
1203  * end the name and begin the optional modifier, but not if it
1204  * is immediately followed by the delimiter (%VAR:%). */
1205  SubstStart = Src;
1206  while (*Src != Delim && !(*Src == _T(':') && Src[1] != Delim))
1207  {
1208  if (!*Src)
1209  goto bad_subst;
1210  Src++;
1211  }
1212 
1213  EndChr = *Src;
1214  *Src = _T('\0');
1215  Var = GetEnvVarOrSpecial(SubstStart);
1216  *Src++ = EndChr;
1217  if (Var == NULL)
1218  {
1219  /* In a batch file, %NONEXISTENT% "expands" to an empty string */
1220  if (bc)
1221  continue;
1222  goto bad_subst;
1223  }
1224  VarLength = _tcslen(Var);
1225 
1226  if (EndChr == Delim)
1227  {
1228  /* %VAR% - use as-is */
1229  APPEND(Var, VarLength)
1230  }
1231  else if (*Src == _T('~'))
1232  {
1233  /* %VAR:~[start][,length]% - substring
1234  * Negative values are offsets from the end */
1235  int Start = _tcstol(Src + 1, &Src, 0);
1236  int End = VarLength;
1237  if (Start < 0)
1238  Start += VarLength;
1239  Start = max(Start, 0);
1240  Start = min(Start, VarLength);
1241  if (*Src == _T(','))
1242  {
1243  End = _tcstol(Src + 1, &Src, 0);
1244  End += (End < 0) ? VarLength : Start;
1245  End = max(End, Start);
1246  End = min(End, VarLength);
1247  }
1248  if (*Src++ != Delim)
1249  goto bad_subst;
1250  APPEND(&Var[Start], End - Start);
1251  }
1252  else
1253  {
1254  /* %VAR:old=new% - replace all occurrences of old with new
1255  * %VAR:*old=new% - replace first occurrence only,
1256  * and remove everything before it */
1257  TCHAR *Old, *New;
1258  DWORD OldLength, NewLength;
1259  BOOL Star = FALSE;
1260  int LastMatch = 0, i = 0;
1261 
1262  if (*Src == _T('*'))
1263  {
1264  Star = TRUE;
1265  Src++;
1266  }
1267 
1268  /* the string to replace may contain the delimiter */
1269  Src = _tcschr(Old = Src, _T('='));
1270  if (Src == NULL)
1271  goto bad_subst;
1272  OldLength = Src++ - Old;
1273  if (OldLength == 0)
1274  goto bad_subst;
1275 
1276  Src = _tcschr(New = Src, Delim);
1277  if (Src == NULL)
1278  goto bad_subst;
1279  NewLength = Src++ - New;
1280 
1281  while (i < VarLength)
1282  {
1283  if (_tcsnicmp(&Var[i], Old, OldLength) == 0)
1284  {
1285  if (!Star)
1286  APPEND(&Var[LastMatch], i - LastMatch)
1287  APPEND(New, NewLength)
1288  i += OldLength;
1289  LastMatch = i;
1290  if (Star)
1291  break;
1292  continue;
1293  }
1294  i++;
1295  }
1296  APPEND(&Var[LastMatch], VarLength - LastMatch)
1297  }
1298  continue;
1299 
1300  bad_subst:
1301  Src = SubstStart;
1302  if (!bc)
1303  APPEND1(Delim)
1304  }
1305  *Dest = _T('\0');
1306  return TRUE;
1307 too_long:
1309  nErrorLevel = 9023;
1310  return FALSE;
1311 #undef APPEND
1312 #undef APPEND1
1313 }
1314 
1315 /* Search the list of FOR contexts for a variable */
1316 static LPTSTR FindForVar(TCHAR Var, BOOL *IsParam0)
1317 {
1318  FOR_CONTEXT *Ctx;
1319  *IsParam0 = FALSE;
1320  for (Ctx = fc; Ctx != NULL; Ctx = Ctx->prev)
1321  {
1322  if ((UINT)(Var - Ctx->firstvar) < Ctx->varcount)
1323  return Ctx->values[Var - Ctx->firstvar];
1324  }
1325  return NULL;
1326 }
1327 
1328 BOOL
1330 {
1331  TCHAR *DestEnd = &Dest[CMDLINE_LENGTH - 1];
1332  while (*Src)
1333  {
1334  if (Src[0] == _T('%'))
1335  {
1336  BOOL Dummy;
1337  LPTSTR End = &Src[2];
1338  LPTSTR Value = NULL;
1339 
1340  if (Src[1] == _T('~'))
1341  Value = GetEnhancedVar(&End, FindForVar);
1342 
1343  if (!Value)
1344  Value = FindForVar(Src[1], &Dummy);
1345 
1346  if (Value)
1347  {
1348  if (Dest + _tcslen(Value) > DestEnd)
1349  return FALSE;
1350  Dest = _stpcpy(Dest, Value);
1351  Src = End;
1352  continue;
1353  }
1354  }
1355  /* Not a variable; just copy the character */
1356  if (Dest >= DestEnd)
1357  return FALSE;
1358  *Dest++ = *Src++;
1359  }
1360  *Dest = _T('\0');
1361  return TRUE;
1362 }
1363 
1364 LPTSTR
1366 {
1367  TCHAR Buf1[CMDLINE_LENGTH];
1368  TCHAR Buf2[CMDLINE_LENGTH];
1369 
1370  /* First, substitute FOR variables */
1371  if (!SubstituteForVars(Line, Buf1))
1372  return NULL;
1373 
1374  if (!bDelayedExpansion || !_tcschr(Buf1, _T('!')))
1375  return cmd_dup(Buf1);
1376 
1377  /* FIXME: Delayed substitutions actually aren't quite the same as
1378  * immediate substitutions. In particular, it's possible to escape
1379  * the exclamation point using ^. */
1380  if (!SubstituteVars(Buf1, Buf2, _T('!')))
1381  return NULL;
1382  return cmd_dup(Buf2);
1383 }
1384 
1385 
1386 /*
1387  * do the prompt/input/process loop
1388  *
1389  */
1390 
1391 BOOL
1392 ReadLine(TCHAR *commandline, BOOL bMore)
1393 {
1395  LPTSTR ip;
1396 
1397  /* if no batch input then... */
1398  if (bc == NULL)
1399  {
1400  if (bMore)
1401  {
1403  }
1404  else
1405  {
1406  /* JPP 19980807 - if echo off, don't print prompt */
1407  if (bEcho)
1408  {
1409  if (!bIgnoreEcho)
1410  ConOutChar(_T('\n'));
1411  PrintPrompt();
1412  }
1413  }
1414 
1415  if (!ReadCommand(readline, CMDLINE_LENGTH - 1))
1416  {
1417  bExit = TRUE;
1418  return FALSE;
1419  }
1420 
1422  {
1423  ConOutChar(_T('\n'));
1424  return FALSE;
1425  }
1426  ip = readline;
1427  }
1428  else
1429  {
1430  ip = ReadBatchLine();
1431  if (!ip)
1432  return FALSE;
1433  }
1434 
1435  return SubstituteVars(ip, commandline, _T('%'));
1436 }
1437 
1438 static VOID
1440 {
1442 
1443  while (!bCanExit || !bExit)
1444  {
1445  Cmd = ParseCommand(NULL);
1446  if (!Cmd)
1447  continue;
1448 
1449  ExecuteCommand(Cmd);
1450  FreeCommand(Cmd);
1451  }
1452 }
1453 
1454 
1455 /*
1456  * control-break handler.
1457  */
1459 {
1460  DWORD dwWritten;
1461  INPUT_RECORD rec;
1462  static BOOL SelfGenerated = FALSE;
1463 
1464  if ((dwCtrlType != CTRL_C_EVENT) &&
1465  (dwCtrlType != CTRL_BREAK_EVENT))
1466  {
1467  return FALSE;
1468  }
1469  else
1470  {
1471  if (SelfGenerated)
1472  {
1473  SelfGenerated = FALSE;
1474  return TRUE;
1475  }
1476  }
1477 
1478  if (!TryEnterCriticalSection(&ChildProcessRunningLock))
1479  {
1480  SelfGenerated = TRUE;
1481  GenerateConsoleCtrlEvent (dwCtrlType, 0);
1482  return TRUE;
1483  }
1484  else
1485  {
1486  LeaveCriticalSection(&ChildProcessRunningLock);
1487  }
1488 
1489  rec.EventType = KEY_EVENT;
1490  rec.Event.KeyEvent.bKeyDown = TRUE;
1491  rec.Event.KeyEvent.wRepeatCount = 1;
1492  rec.Event.KeyEvent.wVirtualKeyCode = _T('C');
1493  rec.Event.KeyEvent.wVirtualScanCode = _T('C') - 35;
1494  rec.Event.KeyEvent.uChar.AsciiChar = _T('C');
1495  rec.Event.KeyEvent.uChar.UnicodeChar = _T('C');
1497 
1499  &rec,
1500  1,
1501  &dwWritten);
1502 
1503  bCtrlBreak = TRUE;
1504  /* FIXME: Handle batch files */
1505 
1506  //ConOutPrintf(_T("^C"));
1507 
1508  return TRUE;
1509 }
1510 
1511 
1513 {
1515 }
1516 
1517 
1519 {
1521 }
1522 
1523 
1524 /*
1525  * show commands and options that are available.
1526  *
1527  */
1528 #if 0
1529 static VOID
1530 ShowCommands(VOID)
1531 {
1532  /* print command list */
1534  PrintCommandList();
1535 
1536  /* print feature list */
1538 
1539 #ifdef FEATURE_ALIASES
1541 #endif
1542 #ifdef FEATURE_HISTORY
1544 #endif
1545 #ifdef FEATURE_UNIX_FILENAME_COMPLETION
1547 #endif
1548 #ifdef FEATURE_DIRECTORY_STACK
1550 #endif
1551 #ifdef FEATURE_REDIRECTION
1553 #endif
1554  ConOutChar(_T('\n'));
1555 }
1556 #endif
1557 
1558 
1559 static VOID
1561 {
1562  LONG lRet;
1563  HKEY hKey;
1564  DWORD dwType, len;
1565  /*
1566  * Buffer big enough to hold the string L"4294967295",
1567  * corresponding to the literal 0xFFFFFFFF (MAX_ULONG) in decimal.
1568  */
1569  DWORD Buffer[6];
1570 
1571  lRet = RegOpenKeyEx(hKeyRoot,
1572  _T("Software\\Microsoft\\Command Processor"),
1573  0,
1575  &hKey);
1576  if (lRet != ERROR_SUCCESS)
1577  return;
1578 
1579 #ifdef INCLUDE_CMD_COLOR
1580  len = sizeof(Buffer);
1581  lRet = RegQueryValueEx(hKey,
1582  _T("DefaultColor"),
1583  NULL,
1584  &dwType,
1585  (LPBYTE)&Buffer,
1586  &len);
1587  if (lRet == ERROR_SUCCESS)
1588  {
1589  /* Overwrite the default attributes */
1590  if (dwType == REG_DWORD)
1591  wDefColor = (WORD)*(PDWORD)Buffer;
1592  else if (dwType == REG_SZ)
1594  }
1595  // else, use the default attributes retrieved before.
1596 #endif
1597 
1598 #if 0
1599  len = sizeof(Buffer);
1600  lRet = RegQueryValueEx(hKey,
1601  _T("DisableUNCCheck"),
1602  NULL,
1603  &dwType,
1604  (LPBYTE)&Buffer,
1605  &len);
1606  if (lRet == ERROR_SUCCESS)
1607  {
1608  /* Overwrite the default setting */
1609  if (dwType == REG_DWORD)
1610  bDisableUNCCheck = !!*(PDWORD)Buffer;
1611  else if (dwType == REG_SZ)
1612  bDisableUNCCheck = (_ttol((PTSTR)Buffer) == 1);
1613  }
1614  // else, use the default setting set globally.
1615 #endif
1616 
1617  len = sizeof(Buffer);
1618  lRet = RegQueryValueEx(hKey,
1619  _T("DelayedExpansion"),
1620  NULL,
1621  &dwType,
1622  (LPBYTE)&Buffer,
1623  &len);
1624  if (lRet == ERROR_SUCCESS)
1625  {
1626  /* Overwrite the default setting */
1627  if (dwType == REG_DWORD)
1628  bDelayedExpansion = !!*(PDWORD)Buffer;
1629  else if (dwType == REG_SZ)
1630  bDelayedExpansion = (_ttol((PTSTR)Buffer) == 1);
1631  }
1632  // else, use the default setting set globally.
1633 
1634  len = sizeof(Buffer);
1635  lRet = RegQueryValueEx(hKey,
1636  _T("EnableExtensions"),
1637  NULL,
1638  &dwType,
1639  (LPBYTE)&Buffer,
1640  &len);
1641  if (lRet == ERROR_SUCCESS)
1642  {
1643  /* Overwrite the default setting */
1644  if (dwType == REG_DWORD)
1645  bEnableExtensions = !!*(PDWORD)Buffer;
1646  else if (dwType == REG_SZ)
1647  bEnableExtensions = (_ttol((PTSTR)Buffer) == 1);
1648  }
1649  // else, use the default setting set globally.
1650 
1651  len = sizeof(Buffer);
1652  lRet = RegQueryValueEx(hKey,
1653  _T("CompletionChar"),
1654  NULL,
1655  &dwType,
1656  (LPBYTE)&Buffer,
1657  &len);
1658  if (lRet == ERROR_SUCCESS)
1659  {
1660  /* Overwrite the default setting */
1661  if (dwType == REG_DWORD)
1663  else if (dwType == REG_SZ)
1665  }
1666  // else, use the default setting set globally.
1667 
1668  /* Validity check */
1670  {
1671  /* Disable autocompletion */
1672  AutoCompletionChar = 0x20;
1673  }
1674 
1675  len = sizeof(Buffer);
1676  lRet = RegQueryValueEx(hKey,
1677  _T("PathCompletionChar"),
1678  NULL,
1679  &dwType,
1680  (LPBYTE)&Buffer,
1681  &len);
1682  if (lRet == ERROR_SUCCESS)
1683  {
1684  /* Overwrite the default setting */
1685  if (dwType == REG_DWORD)
1687  else if (dwType == REG_SZ)
1689  }
1690  // else, use the default setting set globally.
1691 
1692  /* Validity check */
1694  {
1695  /* Disable autocompletion */
1696  PathCompletionChar = 0x20;
1697  }
1698 
1699  /* Adjust completion chars */
1700  if (PathCompletionChar >= 0x20 && AutoCompletionChar < 0x20)
1702  else if (AutoCompletionChar >= 0x20 && PathCompletionChar < 0x20)
1704 
1705  RegCloseKey(hKey);
1706 }
1707 
1708 static VOID
1710 {
1711  LONG lRet;
1712  HKEY hKey;
1713  DWORD dwType, len;
1714  TCHAR AutoRun[2048];
1715 
1716  lRet = RegOpenKeyEx(hKeyRoot,
1717  _T("Software\\Microsoft\\Command Processor"),
1718  0,
1720  &hKey);
1721  if (lRet != ERROR_SUCCESS)
1722  return;
1723 
1724  len = sizeof(AutoRun);
1725  lRet = RegQueryValueEx(hKey,
1726  _T("AutoRun"),
1727  NULL,
1728  &dwType,
1729  (LPBYTE)&AutoRun,
1730  &len);
1731  if ((lRet == ERROR_SUCCESS) && (dwType == REG_EXPAND_SZ || dwType == REG_SZ))
1732  {
1733  if (*AutoRun)
1734  ParseCommandLine(AutoRun);
1735  }
1736 
1737  RegCloseKey(hKey);
1738 }
1739 
1740 /* Get the command that comes after a /C or /K switch */
1741 static VOID
1742 GetCmdLineCommand(TCHAR *commandline, TCHAR *ptr, BOOL AlwaysStrip)
1743 {
1744  TCHAR *LastQuote;
1745 
1746  while (_istspace(*ptr))
1747  ptr++;
1748 
1749  /* Remove leading quote, find final quote */
1750  if (*ptr == _T('"') &&
1751  (LastQuote = _tcsrchr(++ptr, _T('"'))) != NULL)
1752  {
1753  TCHAR *Space;
1754  /* Under certain circumstances, all quotes are preserved.
1755  * CMD /? documents these conditions as follows:
1756  * 1. No /S switch
1757  * 2. Exactly two quotes
1758  * 3. No "special characters" between the quotes
1759  * (CMD /? says &<>()@^| but parentheses did not
1760  * trigger this rule when I tested them.)
1761  * 4. Whitespace exists between the quotes
1762  * 5. Enclosed string is an executable filename
1763  */
1764  *LastQuote = _T('\0');
1765  for (Space = ptr + 1; Space < LastQuote; Space++)
1766  {
1767  if (_istspace(*Space)) /* Rule 4 */
1768  {
1769  if (!AlwaysStrip && /* Rule 1 */
1770  !_tcspbrk(ptr, _T("\"&<>@^|")) && /* Rules 2, 3 */
1771  SearchForExecutable(ptr, commandline)) /* Rule 5 */
1772  {
1773  /* All conditions met: preserve both the quotes */
1774  *LastQuote = _T('"');
1775  _tcscpy(commandline, ptr - 1);
1776  return;
1777  }
1778  break;
1779  }
1780  }
1781 
1782  /* The conditions were not met: remove both the
1783  * leading quote and the last quote */
1784  _tcscpy(commandline, ptr);
1785  _tcscpy(&commandline[LastQuote - ptr], LastQuote + 1);
1786  return;
1787  }
1788 
1789  /* No quotes; just copy */
1790  _tcscpy(commandline, ptr);
1791 }
1792 
1793 
1794 /*
1795  * Set up global initializations and process parameters
1796  */
1797 static VOID
1799 {
1800  HMODULE NtDllModule;
1801  TCHAR commandline[CMDLINE_LENGTH];
1802  TCHAR ModuleName[_MAX_PATH + 1];
1803  // INT nExitCode;
1804 
1805  HANDLE hIn, hOut;
1806 
1807  TCHAR *ptr, *cmdLine, option = 0;
1808  BOOL AlwaysStrip = FALSE;
1809  BOOL AutoRun = TRUE;
1810 
1811  /* Get version information */
1812  InitOSVersion();
1813 
1814  /* Some people like to run ReactOS cmd.exe on Win98, it helps in the
1815  * build process. So don't link implicitly against ntdll.dll, load it
1816  * dynamically instead */
1817  NtDllModule = GetModuleHandle(TEXT("ntdll.dll"));
1818  if (NtDllModule != NULL)
1819  {
1820  NtQueryInformationProcessPtr = (NtQueryInformationProcessProc)GetProcAddress(NtDllModule, "NtQueryInformationProcess");
1821  NtReadVirtualMemoryPtr = (NtReadVirtualMemoryProc)GetProcAddress(NtDllModule, "NtReadVirtualMemory");
1822  }
1823 
1824  /* Load the registry settings */
1827 
1828  /* Initialize our locale */
1829  InitLocale();
1830 
1831  /* Initialize prompt support */
1832  InitPrompt();
1833 
1834 #ifdef FEATURE_DIR_STACK
1835  /* Initialize directory stack */
1837 #endif
1838 
1839 #ifdef FEATURE_HISTORY
1840  /* Initialize history */
1841  InitHistory();
1842 #endif
1843 
1844  /* Set COMSPEC environment variable */
1845  if (GetModuleFileName(NULL, ModuleName, ARRAYSIZE(ModuleName)) != 0)
1846  {
1847  ModuleName[_MAX_PATH] = _T('\0');
1848  SetEnvironmentVariable (_T("COMSPEC"), ModuleName);
1849  }
1850 
1851  /* Add ctrl break handler */
1852  AddBreakHandler();
1853 
1854  /* Set our default console mode */
1855  hOut = ConStreamGetOSHandle(StdOut);
1856  hIn = ConStreamGetOSHandle(StdIn);
1857  SetConsoleMode(hOut, 0); // Reinitialize the console output mode
1860 
1861  cmdLine = GetCommandLine();
1862  TRACE ("[command args: %s]\n", debugstr_aw(cmdLine));
1863 
1864  for (ptr = cmdLine; *ptr; ptr++)
1865  {
1866  if (*ptr == _T('/'))
1867  {
1868  option = _totupper(ptr[1]);
1869  if (option == _T('?'))
1870  {
1872  nErrorLevel = 1;
1873  bExit = TRUE;
1874  return;
1875  }
1876  else if (option == _T('P'))
1877  {
1878  if (!IsExistingFile (_T("\\autoexec.bat")))
1879  {
1880 #ifdef INCLUDE_CMD_DATE
1881  cmd_date (_T(""));
1882 #endif
1883 #ifdef INCLUDE_CMD_TIME
1884  cmd_time (_T(""));
1885 #endif
1886  }
1887  else
1888  {
1889  ParseCommandLine (_T("\\autoexec.bat"));
1890  }
1891  bCanExit = FALSE;
1892  }
1893  else if (option == _T('A'))
1894  {
1896  }
1897  else if (option == _T('C') || option == _T('K') || option == _T('R'))
1898  {
1899  /* Remainder of command line is a command to be run */
1900  break;
1901  }
1902  else if (option == _T('D'))
1903  {
1904  AutoRun = FALSE;
1905  }
1906  else if (option == _T('Q'))
1907  {
1909  }
1910  else if (option == _T('S'))
1911  {
1912  AlwaysStrip = TRUE;
1913  }
1914 #ifdef INCLUDE_CMD_COLOR
1915  else if (!_tcsnicmp(ptr, _T("/T:"), 3))
1916  {
1917  /* Process /T (color) argument; overwrite any previous settings */
1918  wDefColor = (WORD)_tcstoul(&ptr[3], &ptr, 16);
1919  }
1920 #endif
1921  else if (option == _T('U'))
1922  {
1924  }
1925  else if (option == _T('V'))
1926  {
1927  // FIXME: Check validity of the parameter given to V !
1928  bDelayedExpansion = _tcsnicmp(&ptr[2], _T(":OFF"), 4);
1929  }
1930  else if (option == _T('E'))
1931  {
1932  // FIXME: Check validity of the parameter given to E !
1933  bEnableExtensions = _tcsnicmp(&ptr[2], _T(":OFF"), 4);
1934  }
1935  else if (option == _T('X'))
1936  {
1937  /* '/X' is identical to '/E:ON' */
1939  }
1940  else if (option == _T('Y'))
1941  {
1942  /* '/Y' is identical to '/E:OFF' */
1944  }
1945  }
1946  }
1947 
1948 #ifdef INCLUDE_CMD_COLOR
1949  if (wDefColor == 0)
1950  {
1951  /*
1952  * If we still do not have the console colour attribute set,
1953  * retrieve the default one.
1954  */
1956  }
1957 
1958  if (wDefColor != 0)
1960 #endif
1961 
1962  /* Reset the output Standard Streams translation modes and codepage caches */
1963  // ConStreamSetMode(StdIn , OutputStreamMode, InputCodePage );
1966 
1967  if (!*ptr)
1968  {
1969  /* If neither /C or /K was given, display a simple version string */
1970  ConOutChar(_T('\n'));
1972  _T(KERNEL_VERSION_STR),
1973  _T(KERNEL_VERSION_BUILD_STR));
1974  ConOutPuts(_T("(C) Copyright 1998-") _T(COPYRIGHT_YEAR) _T(" ReactOS Team.\n"));
1975  }
1976 
1977  if (AutoRun)
1978  {
1981  }
1982 
1983  if (*ptr)
1984  {
1985  /* Do the /C or /K command */
1986  GetCmdLineCommand(commandline, &ptr[2], AlwaysStrip);
1988  /* nExitCode = */ ParseCommandLine(commandline);
1990  if (option != _T('K'))
1991  {
1992  // nErrorLevel = nExitCode;
1993  bExit = TRUE;
1994  }
1995  }
1996 }
1997 
1998 
2000 {
2001  /* Run cmdexit.bat */
2002  if (IsExistingFile(_T("cmdexit.bat")))
2003  {
2005  ParseCommandLine(_T("cmdexit.bat"));
2006  }
2007  else if (IsExistingFile(_T("\\cmdexit.bat")))
2008  {
2010  ParseCommandLine(_T("\\cmdexit.bat"));
2011  }
2012 
2013 #ifdef FEATURE_DIRECTORY_STACK
2014  /* Destroy directory stack */
2016 #endif
2017 
2018 #ifdef FEATURE_HISTORY
2019  CleanHistory();
2020 #endif
2021 
2022  /* Free GetEnvVar's buffer */
2023  GetEnvVar(NULL);
2024 
2025  /* Remove ctrl break handler */
2027 
2028  /* Restore the default console mode */
2033 
2034  DeleteCriticalSection(&ChildProcessRunningLock);
2035 }
2036 
2037 /*
2038  * main function
2039  */
2040 int _tmain(int argc, const TCHAR *argv[])
2041 {
2042  TCHAR startPath[MAX_PATH];
2043 
2044  InitializeCriticalSection(&ChildProcessRunningLock);
2046 
2047  GetCurrentDirectory(ARRAYSIZE(startPath), startPath);
2048  _tchdir(startPath);
2049 
2050  SetFileApisToOEM();
2053 
2054  /* Initialize the Console Standard Streams */
2058 
2060 
2061  /* Perform general initialization, parse switches on command-line */
2062  Initialize();
2063 
2064  /* Call prompt routine */
2065  ProcessInput();
2066 
2067  /* Do the cleanup */
2068  Cleanup();
2069 
2071 
2073  return nErrorLevel;
2074 }
2075 
2076 /* 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:1439
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:869
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:2040
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:3676
Definition: cmd.h:298
#define _tcsicmp
Definition: xmlstorage.h:205
LPBATCH_CONTEXT bc
Definition: batch.c:66
LPCTSTR GetBatchVar(TCHAR *varName, UINT *varNameLen)
Definition: cmd.c:1118
Definition: ftp_var.h:139
static VOID ExecuteAutoRunFile(HKEY hKeyRoot)
Definition: cmd.c:1709
#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
#define HKEY_CURRENT_USER
Definition: winreg.h:11
static VOID LoadRegistrySettings(HKEY hKeyRoot)
Definition: cmd.c:1560
#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
#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:1742
_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:1163
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: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: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:445
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
WORD wRepeatCount
Definition: wincon.h:226
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
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:809
#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:217
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: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:1458
#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: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:242
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:187
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:186
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:168
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:164
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:1365
#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: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:1392
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:1316
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:261
Definition: sacdrv.h:278
#define NTSTATUS
Definition: precomp.h:20
static HANDLE ExecuteAsync(PARSED_COMMAND *Cmd)
Definition: cmd.c:606
#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:197
#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:1512
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:1329
enum _CON_STREAM_MODE CON_STREAM_MODE
VOID WINAPI SetFileApisToOEM(VOID)
Definition: utils.c:819
static VOID Cleanup(VOID)
Definition: cmd.c:1999
#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: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
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:791
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:640
HANDLE CMD_ModuleHandle
Definition: cmd.c:165
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:729
#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
#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:162
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: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: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:1518
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:1798
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