ReactOS  r73918
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 
148 #ifndef NT_SUCCESS
149 #define NT_SUCCESS(StatCode) ((NTSTATUS)(StatCode) >= 0)
150 #endif
151 
153  PVOID, ULONG, PULONG);
155 
156 BOOL bExit = FALSE; /* indicates EXIT was typed */
157 BOOL bCanExit = TRUE; /* indicates if this shell is exitable */
158 BOOL bCtrlBreak = FALSE; /* Ctrl-Break or Ctrl-C hit */
159 BOOL bIgnoreEcho = FALSE; /* Set this to TRUE to prevent a newline, when executing a command */
160 static BOOL bWaitForCommand = FALSE; /* When we are executing something passed on the commandline after /c or /k */
161 INT nErrorLevel = 0; /* Errorlevel of last launched external program */
172 
175 
176 #ifdef INCLUDE_CMD_COLOR
177 WORD wDefColor; /* 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], szNewTitle[MAX_PATH*2];
319  DWORD dwExitCode = 0;
320  TCHAR *FirstEnd;
321  TCHAR szFullCmdLine [CMDLINE_LENGTH];
322 
323  TRACE ("Execute: \'%s\' \'%s\'\n", debugstr_aw(First), debugstr_aw(Rest));
324 
325  /* Though it was already parsed once, we have a different set of rules
326  for parsing before we pass to CreateProcess */
327  if (First[0] == _T('/') || (First[0] && First[1] == _T(':')))
328  {
329  /* Use the entire first word as the program name (no change) */
330  FirstEnd = First + _tcslen(First);
331  }
332  else
333  {
334  /* If present in the first word, spaces and ,;=/ end the program
335  * name and become the beginning of its parameters. */
336  BOOL bInside = FALSE;
337  for (FirstEnd = First; *FirstEnd; FirstEnd++)
338  {
339  if (!bInside && (_istspace(*FirstEnd) || _tcschr(_T(",;=/"), *FirstEnd)))
340  break;
341  bInside ^= *FirstEnd == _T('"');
342  }
343  }
344 
345  /* Copy the new first/rest into the buffer */
346  first = Full;
347  rest = &Full[FirstEnd - First + 1];
348  _tcscpy(rest, FirstEnd);
349  _tcscat(rest, Rest);
350  *FirstEnd = _T('\0');
351  _tcscpy(first, First);
352 
353  /* check for a drive change */
354  if ((_istalpha (first[0])) && (!_tcscmp (first + 1, _T(":"))))
355  {
356  BOOL working = TRUE;
357  if (!SetCurrentDirectory(first))
358  /* Guess they changed disc or something, handle that gracefully and get to root */
359  {
360  TCHAR str[4];
361  str[0]=first[0];
362  str[1]=_T(':');
363  str[2]=_T('\\');
364  str[3]=0;
365  working = SetCurrentDirectory(str);
366  }
367 
368  if (!working) ConErrResPuts (STRING_FREE_ERROR1);
369  return !working;
370  }
371 
372  /* get the PATH environment variable and parse it */
373  /* search the PATH environment variable for the binary */
374  StripQuotes(First);
375  if (!SearchForExecutable(First, szFullName))
376  {
377  error_bad_command(first);
378  return 1;
379  }
380 
381  GetConsoleTitle(szWindowTitle, ARRAYSIZE(szWindowTitle));
382  bTitleSet = FALSE;
383  _stprintf(szNewTitle, _T("%s - %s%s"), szWindowTitle, First, Rest);
384  SetConsoleTitle(szNewTitle);
385 
386  /* check if this is a .BAT or .CMD file */
387  dot = _tcsrchr (szFullName, _T('.'));
388  if (dot && (!_tcsicmp (dot, _T(".bat")) || !_tcsicmp (dot, _T(".cmd"))))
389  {
390  while (*rest == _T(' '))
391  rest++;
392  TRACE ("[BATCH: %s %s]\n", debugstr_aw(szFullName), debugstr_aw(rest));
393  dwExitCode = Batch(szFullName, first, rest, Cmd);
394  }
395  else
396  {
397  /* exec the program */
398  PROCESS_INFORMATION prci;
399  STARTUPINFO stui;
400 
401  /* build command line for CreateProcess(): FullName + " " + rest */
402  BOOL quoted = !!_tcschr(First, ' ');
403  _tcscpy(szFullCmdLine, quoted ? _T("\"") : _T(""));
404  _tcsncat(szFullCmdLine, First, CMDLINE_LENGTH - _tcslen(szFullCmdLine) - 1);
405  _tcsncat(szFullCmdLine, quoted ? _T("\"") : _T(""), CMDLINE_LENGTH - _tcslen(szFullCmdLine) - 1);
406 
407  if (*rest)
408  {
409  _tcsncat(szFullCmdLine, _T(" "), CMDLINE_LENGTH - _tcslen(szFullCmdLine) - 1);
410  _tcsncat(szFullCmdLine, rest, CMDLINE_LENGTH - _tcslen(szFullCmdLine) - 1);
411  }
412 
413  TRACE ("[EXEC: %s]\n", debugstr_aw(szFullCmdLine));
414 
415  /* fill startup info */
416  memset (&stui, 0, sizeof (STARTUPINFO));
417  stui.cb = sizeof (STARTUPINFO);
420 
421  /* Set the console to standard mode */
424 
425  if (CreateProcess(szFullName,
426  szFullCmdLine,
427  NULL,
428  NULL,
429  TRUE,
430  0, /* CREATE_NEW_PROCESS_GROUP */
431  NULL,
432  NULL,
433  &stui,
434  &prci))
435  {
436  CloseHandle(prci.hThread);
437  }
438  else
439  {
440  // See if we can run this with ShellExecute() ie myfile.xls
442  szFullName,
443  rest,
444  NULL,
445  SW_SHOWNORMAL);
446  }
447 
448  if (prci.hProcess != NULL)
449  {
450  if (bc != NULL || bWaitForCommand || IsConsoleProcess(prci.hProcess))
451  {
452  /* when processing a batch file or starting console processes: execute synchronously */
453  EnterCriticalSection(&ChildProcessRunningLock);
455 
457 
458  LeaveCriticalSection(&ChildProcessRunningLock);
459 
460  GetExitCodeProcess(prci.hProcess, &dwExitCode);
461  nErrorLevel = (INT)dwExitCode;
462  }
463  CloseHandle(prci.hProcess);
464  }
465  else
466  {
467  TRACE ("[ShellExecute failed!: %s]\n", debugstr_aw(Full));
468  error_bad_command(first);
469  dwExitCode = 1;
470  }
471 
472  /* Restore our default console mode */
477  }
478 
479  /* Get code page if it has been changed */
482  if (!bTitleSet)
483  SetConsoleTitle(szWindowTitle);
484 
485  return dwExitCode;
486 }
487 
488 
489 /*
490  * look through the internal commands and determine whether or not this
491  * command is one of them. If it is, call the command. If not, call
492  * execute to run it as an external program.
493  *
494  * first - first word on command line
495  * rest - rest of command line
496  */
497 INT
499 {
500  TCHAR *com;
501  TCHAR *cp;
502  LPTSTR param; /* pointer to command's parameters */
503  INT cl;
504  LPCOMMAND cmdptr;
505  BOOL nointernal = FALSE;
506  INT ret;
507 
508  TRACE ("DoCommand: (\'%s\' \'%s\')\n", debugstr_aw(first), debugstr_aw(rest));
509 
510  /* full command line */
511  com = cmd_alloc((_tcslen(first) + _tcslen(rest) + 2) * sizeof(TCHAR));
512  if (com == NULL)
513  {
515  return 1;
516  }
517 
518  /* If present in the first word, these characters end the name of an
519  * internal command and become the beginning of its parameters. */
520  cp = first + _tcscspn(first, _T("\t +,/;=[]"));
521 
522  for (cl = 0; cl < (cp - first); cl++)
523  {
524  /* These characters do it too, but if one of them is present,
525  * then we check to see if the word is a file name and skip
526  * checking for internal commands if so.
527  * This allows running programs with names like "echo.exe" */
528  if (_tcschr(_T(".:\\"), first[cl]))
529  {
530  TCHAR tmp = *cp;
531  *cp = _T('\0');
532  nointernal = IsExistingFile(first);
533  *cp = tmp;
534  break;
535  }
536  }
537 
538  /* Scan internal command table */
539  for (cmdptr = cmds; !nointernal && cmdptr->name; cmdptr++)
540  {
541  if (!_tcsnicmp(first, cmdptr->name, cl) && cmdptr->name[cl] == _T('\0'))
542  {
543  _tcscpy(com, first);
544  _tcscat(com, rest);
545  param = &com[cl];
546 
547  /* Skip over whitespace to rest of line, exclude 'echo' command */
548  if (_tcsicmp(cmdptr->name, _T("echo")) != 0)
549  while (_istspace(*param))
550  param++;
551  ret = cmdptr->func(param);
552  cmd_free(com);
553  return ret;
554  }
555  }
556 
557  ret = Execute(com, first, rest, Cmd);
558  cmd_free(com);
559  return ret;
560 }
561 
562 
563 /*
564  * process the command line and execute the appropriate functions
565  * full input/output redirection and piping are supported
566  */
568 {
569  INT Ret = 0;
571  if (Cmd)
572  {
573  Ret = ExecuteCommand(Cmd);
574  FreeCommand(Cmd);
575  }
576  return Ret;
577 }
578 
579 /* Execute a command without waiting for it to finish. If it's an internal
580  * command or batch file, we must create a new cmd.exe process to handle it.
581  * TODO: For now, this just always creates a cmd.exe process.
582  * This works, but is inefficient for running external programs,
583  * which could just be run directly. */
584 static HANDLE
586 {
587  TCHAR CmdPath[MAX_PATH];
588  TCHAR CmdParams[CMDLINE_LENGTH], *ParamsEnd;
589  STARTUPINFO stui;
590  PROCESS_INFORMATION prci;
591 
592  /* Get the path to cmd.exe */
593  GetModuleFileName(NULL, CmdPath, MAX_PATH);
594 
595  /* Build the parameter string to pass to cmd.exe */
596  ParamsEnd = _stpcpy(CmdParams, _T("/S/D/C\""));
597  ParamsEnd = Unparse(Cmd, ParamsEnd, &CmdParams[CMDLINE_LENGTH - 2]);
598  if (!ParamsEnd)
599  {
601  return NULL;
602  }
603  _tcscpy(ParamsEnd, _T("\""));
604 
605  memset(&stui, 0, sizeof stui);
606  stui.cb = sizeof(STARTUPINFO);
607  if (!CreateProcess(CmdPath, CmdParams, NULL, NULL, TRUE, 0,
608  NULL, NULL, &stui, &prci))
609  {
611  return NULL;
612  }
613 
614  CloseHandle(prci.hThread);
615  return prci.hProcess;
616 }
617 
618 static VOID
620 {
621 #ifdef FEATURE_REDIRECTION
622  HANDLE hInput = NULL;
623  HANDLE hOldConIn = GetStdHandle(STD_INPUT_HANDLE);
624  HANDLE hOldConOut = GetStdHandle(STD_OUTPUT_HANDLE);
626  INT nProcesses = 0;
627  DWORD dwExitCode;
628 
629  /* Do all but the last pipe command */
630  do
631  {
632  HANDLE hPipeRead, hPipeWrite;
633  if (nProcesses > (MAXIMUM_WAIT_OBJECTS - 2))
634  {
636  goto failed;
637  }
638 
639  /* Create the pipe that this process will write into.
640  * Make the handles non-inheritable initially, because this
641  * process shouldn't inherit the reading handle. */
642  if (!CreatePipe(&hPipeRead, &hPipeWrite, NULL, 0))
643  {
644  error_no_pipe();
645  goto failed;
646  }
647 
648  /* The writing side of the pipe is STDOUT for this process */
650  SetStdHandle(STD_OUTPUT_HANDLE, hPipeWrite);
651 
652  /* Execute it (error check is done later for easier cleanup) */
653  hProcess[nProcesses] = ExecuteAsync(Cmd->Subcommands);
654  CloseHandle(hPipeWrite);
655  if (hInput)
656  CloseHandle(hInput);
657 
658  /* The reading side of the pipe will be STDIN for the next process */
660  SetStdHandle(STD_INPUT_HANDLE, hPipeRead);
661  hInput = hPipeRead;
662 
663  if (!hProcess[nProcesses])
664  goto failed;
665  nProcesses++;
666 
667  Cmd = Cmd->Subcommands->Next;
668  } while (Cmd->Type == C_PIPE);
669 
670  /* The last process uses the original STDOUT */
671  SetStdHandle(STD_OUTPUT_HANDLE, hOldConOut);
672  hProcess[nProcesses] = ExecuteAsync(Cmd);
673  if (!hProcess[nProcesses])
674  goto failed;
675  nProcesses++;
676  CloseHandle(hInput);
677  SetStdHandle(STD_INPUT_HANDLE, hOldConIn);
678 
679  /* Wait for all processes to complete */
680  EnterCriticalSection(&ChildProcessRunningLock);
681  WaitForMultipleObjects(nProcesses, hProcess, TRUE, INFINITE);
682  LeaveCriticalSection(&ChildProcessRunningLock);
683 
684  /* Use the exit code of the last process in the pipeline */
685  GetExitCodeProcess(hProcess[nProcesses - 1], &dwExitCode);
686  nErrorLevel = (INT)dwExitCode;
687 
688  while (--nProcesses >= 0)
689  CloseHandle(hProcess[nProcesses]);
690  return;
691 
692 failed:
693  if (hInput)
694  CloseHandle(hInput);
695  while (--nProcesses >= 0)
696  {
697  TerminateProcess(hProcess[nProcesses], 0);
698  CloseHandle(hProcess[nProcesses]);
699  }
700  SetStdHandle(STD_INPUT_HANDLE, hOldConIn);
701  SetStdHandle(STD_OUTPUT_HANDLE, hOldConOut);
702 #endif
703 }
704 
705 INT
707 {
708  PARSED_COMMAND *Sub;
709  LPTSTR First, Rest;
710  INT Ret = 0;
711 
712  if (!PerformRedirection(Cmd->Redirections))
713  return 1;
714 
715  switch (Cmd->Type)
716  {
717  case C_COMMAND:
718  Ret = 1;
719  First = DoDelayedExpansion(Cmd->Command.First);
720  if (First)
721  {
722  Rest = DoDelayedExpansion(Cmd->Command.Rest);
723  if (Rest)
724  {
725  Ret = DoCommand(First, Rest, Cmd);
726  cmd_free(Rest);
727  }
728  cmd_free(First);
729  }
730  break;
731  case C_QUIET:
732  case C_BLOCK:
733  case C_MULTI:
734  for (Sub = Cmd->Subcommands; Sub; Sub = Sub->Next)
735  Ret = ExecuteCommand(Sub);
736  break;
737  case C_IFFAILURE:
738  Sub = Cmd->Subcommands;
739  Ret = ExecuteCommand(Sub);
740  if (Ret != 0)
741  {
742  nErrorLevel = Ret;
743  Ret = ExecuteCommand(Sub->Next);
744  }
745  break;
746  case C_IFSUCCESS:
747  Sub = Cmd->Subcommands;
748  Ret = ExecuteCommand(Sub);
749  if (Ret == 0)
750  Ret = ExecuteCommand(Sub->Next);
751  break;
752  case C_PIPE:
753  ExecutePipeline(Cmd);
754  break;
755  case C_IF:
756  Ret = ExecuteIf(Cmd);
757  break;
758  case C_FOR:
759  Ret = ExecuteFor(Cmd);
760  break;
761  }
762 
764  return Ret;
765 }
766 
767 LPTSTR
769 {
770  static LPTSTR ret = NULL;
771  UINT size;
772 
773  cmd_free(ret);
774  ret = NULL;
775  size = GetEnvironmentVariable(varName, NULL, 0);
776  if (size > 0)
777  {
778  ret = cmd_alloc(size * sizeof(TCHAR));
779  if (ret != NULL)
780  GetEnvironmentVariable(varName, ret, size + 1);
781  }
782  return ret;
783 }
784 
785 LPCTSTR
787 {
788  static TCHAR ret[MAX_PATH];
789 
790  LPTSTR var = GetEnvVar(varName);
791  if (var)
792  return var;
793 
794  /* env var doesn't exist, look for a "special" one */
795  /* %CD% */
796  if (_tcsicmp(varName,_T("cd")) ==0)
797  {
799  return ret;
800  }
801  /* %TIME% */
802  else if (_tcsicmp(varName,_T("time")) ==0)
803  {
804  return GetTimeString();
805  }
806  /* %DATE% */
807  else if (_tcsicmp(varName,_T("date")) ==0)
808  {
809  return GetDateString();
810  }
811 
812  /* %RANDOM% */
813  else if (_tcsicmp(varName,_T("random")) ==0)
814  {
815  /* Get random number */
816  _itot(rand(),ret,10);
817  return ret;
818  }
819 
820  /* %CMDCMDLINE% */
821  else if (_tcsicmp(varName,_T("cmdcmdline")) ==0)
822  {
823  return GetCommandLine();
824  }
825 
826  /* %CMDEXTVERSION% */
827  else if (_tcsicmp(varName,_T("cmdextversion")) ==0)
828  {
829  /* Set version number to 2 */
830  _itot(2,ret,10);
831  return ret;
832  }
833 
834  /* %ERRORLEVEL% */
835  else if (_tcsicmp(varName,_T("errorlevel")) ==0)
836  {
837  _itot(nErrorLevel,ret,10);
838  return ret;
839  }
840 
841  return NULL;
842 }
843 
844 /* Handle the %~var syntax */
845 static LPTSTR
846 GetEnhancedVar(TCHAR **pFormat, LPTSTR (*GetVar)(TCHAR, BOOL *))
847 {
848  static const TCHAR ModifierTable[] = _T("dpnxfsatz");
849  enum {
850  M_DRIVE = 1, /* D: drive letter */
851  M_PATH = 2, /* P: path */
852  M_NAME = 4, /* N: filename */
853  M_EXT = 8, /* X: extension */
854  M_FULL = 16, /* F: full path (drive+path+name+ext) */
855  M_SHORT = 32, /* S: full path (drive+path+name+ext), use short names */
856  M_ATTR = 64, /* A: attributes */
857  M_TIME = 128, /* T: modification time */
858  M_SIZE = 256, /* Z: file size */
859  } Modifiers = 0;
860 
861  TCHAR *Format, *FormatEnd;
862  TCHAR *PathVarName = NULL;
863  LPTSTR Variable;
864  TCHAR *VarEnd;
865  BOOL VariableIsParam0;
866  TCHAR FullPath[MAX_PATH];
867  TCHAR FixedPath[MAX_PATH], *Filename, *Extension;
868  HANDLE hFind;
869  WIN32_FIND_DATA w32fd;
870  TCHAR *In, *Out;
871 
872  static TCHAR Result[CMDLINE_LENGTH];
873 
874  /* There is ambiguity between modifier characters and FOR variables;
875  * the rule that cmd uses is to pick the longest possible match.
876  * For example, if there is a %n variable, then out of %~anxnd,
877  * %~anxn will be substituted rather than just %~an. */
878 
879  /* First, go through as many modifier characters as possible */
880  FormatEnd = Format = *pFormat;
881  while (*FormatEnd && _tcschr(ModifierTable, _totlower(*FormatEnd)))
882  FormatEnd++;
883 
884  if (*FormatEnd == _T('$'))
885  {
886  /* $PATH: syntax */
887  PathVarName = FormatEnd + 1;
888  FormatEnd = _tcschr(PathVarName, _T(':'));
889  if (!FormatEnd)
890  return NULL;
891 
892  /* Must be immediately followed by the variable */
893  Variable = GetVar(*++FormatEnd, &VariableIsParam0);
894  if (!Variable)
895  return NULL;
896  }
897  else
898  {
899  /* Backtrack if necessary to get a variable name match */
900  while (!(Variable = GetVar(*FormatEnd, &VariableIsParam0)))
901  {
902  if (FormatEnd == Format)
903  return NULL;
904  FormatEnd--;
905  }
906  }
907 
908  for (; Format < FormatEnd && *Format != _T('$'); Format++)
909  Modifiers |= 1 << (_tcschr(ModifierTable, _totlower(*Format)) - ModifierTable);
910 
911  *pFormat = FormatEnd + 1;
912 
913  /* Exclude the leading and trailing quotes */
914  VarEnd = &Variable[_tcslen(Variable)];
915  if (*Variable == _T('"'))
916  {
917  Variable++;
918  if (VarEnd > Variable && VarEnd[-1] == _T('"'))
919  VarEnd--;
920  }
921 
922  if ((char *)VarEnd - (char *)Variable >= sizeof Result)
923  return _T("");
924  memcpy(Result, Variable, (char *)VarEnd - (char *)Variable);
925  Result[VarEnd - Variable] = _T('\0');
926 
927  if (PathVarName)
928  {
929  /* $PATH: syntax - search the directories listed in the
930  * specified environment variable for the file */
931  LPTSTR PathVar;
932  FormatEnd[-1] = _T('\0');
933  PathVar = GetEnvVar(PathVarName);
934  FormatEnd[-1] = _T(':');
935  if (!PathVar ||
936  !SearchPath(PathVar, Result, NULL, MAX_PATH, FullPath, NULL))
937  {
938  return _T("");
939  }
940  }
941  else if (Modifiers == 0)
942  {
943  /* For plain %~var with no modifiers, just return the variable without quotes */
944  return Result;
945  }
946  else if (VariableIsParam0)
947  {
948  /* Special case: If the variable is %0 and modifier characters are present,
949  * use the batch file's path (which includes the .bat/.cmd extension)
950  * rather than the actual %0 variable (which might not). */
951  _tcscpy(FullPath, bc->BatchFilePath);
952  }
953  else
954  {
955  /* Convert the variable, now without quotes, to a full path */
956  if (!GetFullPathName(Result, MAX_PATH, FullPath, NULL))
957  return _T("");
958  }
959 
960  /* Next step is to change the path to fix letter case (e.g.
961  * C:\ReAcToS -> C:\ReactOS) and, if requested with the S modifier,
962  * replace long filenames with short. */
963 
964  In = FullPath;
965  Out = FixedPath;
966 
967  /* Copy drive letter */
968  *Out++ = *In++;
969  *Out++ = *In++;
970  *Out++ = *In++;
971  /* Loop over each \-separated component in the path */
972  do {
973  TCHAR *Next = _tcschr(In, _T('\\'));
974  if (Next)
975  *Next++ = _T('\0');
976  /* Use FindFirstFile to get the correct name */
977  if (Out + _tcslen(In) + 1 >= &FixedPath[MAX_PATH])
978  return _T("");
979  _tcscpy(Out, In);
980  hFind = FindFirstFile(FixedPath, &w32fd);
981  /* If it doesn't exist, just leave the name as it was given */
982  if (hFind != INVALID_HANDLE_VALUE)
983  {
984  LPTSTR FixedComponent = w32fd.cFileName;
985  if (*w32fd.cAlternateFileName &&
986  ((Modifiers & M_SHORT) || !_tcsicmp(In, w32fd.cAlternateFileName)))
987  {
988  FixedComponent = w32fd.cAlternateFileName;
989  }
990  FindClose(hFind);
991 
992  if (Out + _tcslen(FixedComponent) + 1 >= &FixedPath[MAX_PATH])
993  return _T("");
994  _tcscpy(Out, FixedComponent);
995  }
996  Filename = Out;
997  Out += _tcslen(Out);
998  *Out++ = _T('\\');
999 
1000  In = Next;
1001  } while (In != NULL);
1002  Out[-1] = _T('\0');
1003 
1004  /* Build the result string. Start with attributes, modification time, and
1005  * file size. If the file didn't exist, these fields will all be empty. */
1006  Out = Result;
1007  if (hFind != INVALID_HANDLE_VALUE)
1008  {
1009  if (Modifiers & M_ATTR)
1010  {
1011  static const struct {
1012  TCHAR Character;
1013  WORD Value;
1014  } *Attrib, Table[] = {
1015  { _T('d'), FILE_ATTRIBUTE_DIRECTORY },
1016  { _T('r'), FILE_ATTRIBUTE_READONLY },
1017  { _T('a'), FILE_ATTRIBUTE_ARCHIVE },
1018  { _T('h'), FILE_ATTRIBUTE_HIDDEN },
1019  { _T('s'), FILE_ATTRIBUTE_SYSTEM },
1020  { _T('c'), FILE_ATTRIBUTE_COMPRESSED },
1021  { _T('o'), FILE_ATTRIBUTE_OFFLINE },
1022  { _T('t'), FILE_ATTRIBUTE_TEMPORARY },
1023  { _T('l'), FILE_ATTRIBUTE_REPARSE_POINT },
1024  };
1025  for (Attrib = Table; Attrib != &Table[9]; Attrib++)
1026  {
1027  *Out++ = w32fd.dwFileAttributes & Attrib->Value
1028  ? Attrib->Character
1029  : _T('-');
1030  }
1031  *Out++ = _T(' ');
1032  }
1033  if (Modifiers & M_TIME)
1034  {
1035  FILETIME ft;
1036  SYSTEMTIME st;
1037  FileTimeToLocalFileTime(&w32fd.ftLastWriteTime, &ft);
1038  FileTimeToSystemTime(&ft, &st);
1039 
1040  Out += FormatDate(Out, &st, TRUE);
1041  *Out++ = _T(' ');
1042  Out += FormatTime(Out, &st);
1043  *Out++ = _T(' ');
1044  }
1045  if (Modifiers & M_SIZE)
1046  {
1048  Size.LowPart = w32fd.nFileSizeLow;
1049  Size.HighPart = w32fd.nFileSizeHigh;
1050  Out += _stprintf(Out, _T("%I64u "), Size.QuadPart);
1051  }
1052  }
1053 
1054  /* When using the path-searching syntax or the S modifier,
1055  * at least part of the file path is always included.
1056  * If none of the DPNX modifiers are present, include the full path */
1057  if (PathVarName || (Modifiers & M_SHORT))
1058  if ((Modifiers & (M_DRIVE | M_PATH | M_NAME | M_EXT)) == 0)
1059  Modifiers |= M_FULL;
1060 
1061  /* Now add the requested parts of the name.
1062  * With the F modifier, add all parts to form the full path. */
1063  Extension = _tcsrchr(Filename, _T('.'));
1064  if (Modifiers & (M_DRIVE | M_FULL))
1065  {
1066  *Out++ = FixedPath[0];
1067  *Out++ = FixedPath[1];
1068  }
1069  if (Modifiers & (M_PATH | M_FULL))
1070  {
1071  memcpy(Out, &FixedPath[2], (char *)Filename - (char *)&FixedPath[2]);
1072  Out += Filename - &FixedPath[2];
1073  }
1074  if (Modifiers & (M_NAME | M_FULL))
1075  {
1076  while (*Filename && Filename != Extension)
1077  *Out++ = *Filename++;
1078  }
1079  if (Modifiers & (M_EXT | M_FULL))
1080  {
1081  if (Extension)
1082  Out = _stpcpy(Out, Extension);
1083  }
1084 
1085  /* Trim trailing space which otherwise would appear as a
1086  * result of using the A/T/Z modifiers but no others. */
1087  while (Out != &Result[0] && Out[-1] == _T(' '))
1088  Out--;
1089  *Out = _T('\0');
1090 
1091  return Result;
1092 }
1093 
1094 LPCTSTR
1095 GetBatchVar(TCHAR *varName, UINT *varNameLen)
1096 {
1097  LPCTSTR ret;
1098  TCHAR *varNameEnd;
1099  BOOL dummy;
1100 
1101  *varNameLen = 1;
1102 
1103  switch ( *varName )
1104  {
1105  case _T('~'):
1106  varNameEnd = varName + 1;
1107  ret = GetEnhancedVar(&varNameEnd, FindArg);
1108  if (!ret)
1109  {
1110  error_syntax(varName);
1111  return NULL;
1112  }
1113  *varNameLen = varNameEnd - varName;
1114  return ret;
1115  case _T('0'):
1116  case _T('1'):
1117  case _T('2'):
1118  case _T('3'):
1119  case _T('4'):
1120  case _T('5'):
1121  case _T('6'):
1122  case _T('7'):
1123  case _T('8'):
1124  case _T('9'):
1125  return FindArg(*varName, &dummy);
1126 
1127  case _T('*'):
1128  //
1129  // Copy over the raw params(not including the batch file name
1130  //
1131  return bc->raw_params;
1132 
1133  case _T('%'):
1134  return _T("%");
1135  }
1136  return NULL;
1137 }
1138 
1139 BOOL
1140 SubstituteVars(TCHAR *Src, TCHAR *Dest, TCHAR Delim)
1141 {
1142 #define APPEND(From, Length) { \
1143  if (Dest + (Length) > DestEnd) \
1144  goto too_long; \
1145  memcpy(Dest, From, (Length) * sizeof(TCHAR)); \
1146  Dest += Length; }
1147 #define APPEND1(Char) { \
1148  if (Dest >= DestEnd) \
1149  goto too_long; \
1150  *Dest++ = Char; }
1151 
1152  TCHAR *DestEnd = Dest + CMDLINE_LENGTH - 1;
1153  const TCHAR *Var;
1154  int VarLength;
1155  TCHAR *SubstStart;
1156  TCHAR EndChr;
1157  while (*Src)
1158  {
1159  if (*Src != Delim)
1160  {
1161  APPEND1(*Src++)
1162  continue;
1163  }
1164 
1165  Src++;
1166  if (bc && Delim == _T('%'))
1167  {
1168  UINT NameLen;
1169  Var = GetBatchVar(Src, &NameLen);
1170  if (Var != NULL)
1171  {
1172  VarLength = _tcslen(Var);
1173  APPEND(Var, VarLength)
1174  Src += NameLen;
1175  continue;
1176  }
1177  }
1178 
1179  /* Find the end of the variable name. A colon (:) will usually
1180  * end the name and begin the optional modifier, but not if it
1181  * is immediately followed by the delimiter (%VAR:%). */
1182  SubstStart = Src;
1183  while (*Src != Delim && !(*Src == _T(':') && Src[1] != Delim))
1184  {
1185  if (!*Src)
1186  goto bad_subst;
1187  Src++;
1188  }
1189 
1190  EndChr = *Src;
1191  *Src = _T('\0');
1192  Var = GetEnvVarOrSpecial(SubstStart);
1193  *Src++ = EndChr;
1194  if (Var == NULL)
1195  {
1196  /* In a batch file, %NONEXISTENT% "expands" to an empty string */
1197  if (bc)
1198  continue;
1199  goto bad_subst;
1200  }
1201  VarLength = _tcslen(Var);
1202 
1203  if (EndChr == Delim)
1204  {
1205  /* %VAR% - use as-is */
1206  APPEND(Var, VarLength)
1207  }
1208  else if (*Src == _T('~'))
1209  {
1210  /* %VAR:~[start][,length]% - substring
1211  * Negative values are offsets from the end */
1212  int Start = _tcstol(Src + 1, &Src, 0);
1213  int End = VarLength;
1214  if (Start < 0)
1215  Start += VarLength;
1216  Start = max(Start, 0);
1217  Start = min(Start, VarLength);
1218  if (*Src == _T(','))
1219  {
1220  End = _tcstol(Src + 1, &Src, 0);
1221  End += (End < 0) ? VarLength : Start;
1222  End = max(End, Start);
1223  End = min(End, VarLength);
1224  }
1225  if (*Src++ != Delim)
1226  goto bad_subst;
1227  APPEND(&Var[Start], End - Start);
1228  }
1229  else
1230  {
1231  /* %VAR:old=new% - replace all occurrences of old with new
1232  * %VAR:*old=new% - replace first occurrence only,
1233  * and remove everything before it */
1234  TCHAR *Old, *New;
1235  DWORD OldLength, NewLength;
1236  BOOL Star = FALSE;
1237  int LastMatch = 0, i = 0;
1238 
1239  if (*Src == _T('*'))
1240  {
1241  Star = TRUE;
1242  Src++;
1243  }
1244 
1245  /* the string to replace may contain the delimiter */
1246  Src = _tcschr(Old = Src, _T('='));
1247  if (Src == NULL)
1248  goto bad_subst;
1249  OldLength = Src++ - Old;
1250  if (OldLength == 0)
1251  goto bad_subst;
1252 
1253  Src = _tcschr(New = Src, Delim);
1254  if (Src == NULL)
1255  goto bad_subst;
1256  NewLength = Src++ - New;
1257 
1258  while (i < VarLength)
1259  {
1260  if (_tcsnicmp(&Var[i], Old, OldLength) == 0)
1261  {
1262  if (!Star)
1263  APPEND(&Var[LastMatch], i - LastMatch)
1264  APPEND(New, NewLength)
1265  i += OldLength;
1266  LastMatch = i;
1267  if (Star)
1268  break;
1269  continue;
1270  }
1271  i++;
1272  }
1273  APPEND(&Var[LastMatch], VarLength - LastMatch)
1274  }
1275  continue;
1276 
1277  bad_subst:
1278  Src = SubstStart;
1279  if (!bc)
1280  APPEND1(Delim)
1281  }
1282  *Dest = _T('\0');
1283  return TRUE;
1284 too_long:
1286  nErrorLevel = 9023;
1287  return FALSE;
1288 #undef APPEND
1289 #undef APPEND1
1290 }
1291 
1292 /* Search the list of FOR contexts for a variable */
1293 static LPTSTR FindForVar(TCHAR Var, BOOL *IsParam0)
1294 {
1295  FOR_CONTEXT *Ctx;
1296  *IsParam0 = FALSE;
1297  for (Ctx = fc; Ctx != NULL; Ctx = Ctx->prev)
1298  {
1299  if ((UINT)(Var - Ctx->firstvar) < Ctx->varcount)
1300  return Ctx->values[Var - Ctx->firstvar];
1301  }
1302  return NULL;
1303 }
1304 
1305 BOOL
1307 {
1308  TCHAR *DestEnd = &Dest[CMDLINE_LENGTH - 1];
1309  while (*Src)
1310  {
1311  if (Src[0] == _T('%'))
1312  {
1313  BOOL Dummy;
1314  LPTSTR End = &Src[2];
1315  LPTSTR Value = NULL;
1316 
1317  if (Src[1] == _T('~'))
1318  Value = GetEnhancedVar(&End, FindForVar);
1319 
1320  if (!Value)
1321  Value = FindForVar(Src[1], &Dummy);
1322 
1323  if (Value)
1324  {
1325  if (Dest + _tcslen(Value) > DestEnd)
1326  return FALSE;
1327  Dest = _stpcpy(Dest, Value);
1328  Src = End;
1329  continue;
1330  }
1331  }
1332  /* Not a variable; just copy the character */
1333  if (Dest >= DestEnd)
1334  return FALSE;
1335  *Dest++ = *Src++;
1336  }
1337  *Dest = _T('\0');
1338  return TRUE;
1339 }
1340 
1341 LPTSTR
1343 {
1344  TCHAR Buf1[CMDLINE_LENGTH];
1345  TCHAR Buf2[CMDLINE_LENGTH];
1346 
1347  /* First, substitute FOR variables */
1348  if (!SubstituteForVars(Line, Buf1))
1349  return NULL;
1350 
1351  if (!bDelayedExpansion || !_tcschr(Buf1, _T('!')))
1352  return cmd_dup(Buf1);
1353 
1354  /* FIXME: Delayed substitutions actually aren't quite the same as
1355  * immediate substitutions. In particular, it's possible to escape
1356  * the exclamation point using ^. */
1357  if (!SubstituteVars(Buf1, Buf2, _T('!')))
1358  return NULL;
1359  return cmd_dup(Buf2);
1360 }
1361 
1362 
1363 /*
1364  * do the prompt/input/process loop
1365  *
1366  */
1367 
1368 BOOL
1369 ReadLine(TCHAR *commandline, BOOL bMore)
1370 {
1372  LPTSTR ip;
1373 
1374  /* if no batch input then... */
1375  if (bc == NULL)
1376  {
1377  if (bMore)
1378  {
1380  }
1381  else
1382  {
1383  /* JPP 19980807 - if echo off, don't print prompt */
1384  if (bEcho)
1385  {
1386  if (!bIgnoreEcho)
1387  ConOutChar(_T('\n'));
1388  PrintPrompt();
1389  }
1390  }
1391 
1392  if (!ReadCommand(readline, CMDLINE_LENGTH - 1))
1393  {
1394  bExit = TRUE;
1395  return FALSE;
1396  }
1397 
1399  {
1400  ConOutChar(_T('\n'));
1401  return FALSE;
1402  }
1403  ip = readline;
1404  }
1405  else
1406  {
1407  ip = ReadBatchLine();
1408  if (!ip)
1409  return FALSE;
1410  }
1411 
1412  return SubstituteVars(ip, commandline, _T('%'));
1413 }
1414 
1415 static VOID
1417 {
1419 
1420  while (!bCanExit || !bExit)
1421  {
1422  Cmd = ParseCommand(NULL);
1423  if (!Cmd)
1424  continue;
1425 
1426  ExecuteCommand(Cmd);
1427  FreeCommand(Cmd);
1428  }
1429 }
1430 
1431 
1432 /*
1433  * control-break handler.
1434  */
1436 {
1437  DWORD dwWritten;
1438  INPUT_RECORD rec;
1439  static BOOL SelfGenerated = FALSE;
1440 
1441  if ((dwCtrlType != CTRL_C_EVENT) &&
1442  (dwCtrlType != CTRL_BREAK_EVENT))
1443  {
1444  return FALSE;
1445  }
1446  else
1447  {
1448  if (SelfGenerated)
1449  {
1450  SelfGenerated = FALSE;
1451  return TRUE;
1452  }
1453  }
1454 
1455  if (!TryEnterCriticalSection(&ChildProcessRunningLock))
1456  {
1457  SelfGenerated = TRUE;
1458  GenerateConsoleCtrlEvent (dwCtrlType, 0);
1459  return TRUE;
1460  }
1461  else
1462  {
1463  LeaveCriticalSection(&ChildProcessRunningLock);
1464  }
1465 
1466  rec.EventType = KEY_EVENT;
1467  rec.Event.KeyEvent.bKeyDown = TRUE;
1468  rec.Event.KeyEvent.wRepeatCount = 1;
1469  rec.Event.KeyEvent.wVirtualKeyCode = _T('C');
1470  rec.Event.KeyEvent.wVirtualScanCode = _T('C') - 35;
1471  rec.Event.KeyEvent.uChar.AsciiChar = _T('C');
1472  rec.Event.KeyEvent.uChar.UnicodeChar = _T('C');
1474 
1476  &rec,
1477  1,
1478  &dwWritten);
1479 
1480  bCtrlBreak = TRUE;
1481  /* FIXME: Handle batch files */
1482 
1483  //ConOutPrintf(_T("^C"));
1484 
1485  return TRUE;
1486 }
1487 
1488 
1490 {
1492 }
1493 
1494 
1496 {
1498 }
1499 
1500 
1501 /*
1502  * show commands and options that are available.
1503  *
1504  */
1505 #if 0
1506 static VOID
1507 ShowCommands (VOID)
1508 {
1509  /* print command list */
1511  PrintCommandList();
1512 
1513  /* print feature list */
1515 
1516 #ifdef FEATURE_ALIASES
1518 #endif
1519 #ifdef FEATURE_HISTORY
1521 #endif
1522 #ifdef FEATURE_UNIX_FILENAME_COMPLETION
1524 #endif
1525 #ifdef FEATURE_DIRECTORY_STACK
1527 #endif
1528 #ifdef FEATURE_REDIRECTION
1530 #endif
1531  ConOutChar(_T('\n'));
1532 }
1533 #endif
1534 
1535 static VOID
1537 {
1538  TCHAR autorun[2048];
1539  DWORD len = sizeof autorun;
1540  HKEY hkey;
1541 
1542  if (RegOpenKeyEx(hkeyRoot,
1543  _T("SOFTWARE\\Microsoft\\Command Processor"),
1544  0,
1545  KEY_READ,
1546  &hkey) == ERROR_SUCCESS)
1547  {
1548  if (RegQueryValueEx(hkey,
1549  _T("AutoRun"),
1550  0,
1551  0,
1552  (LPBYTE)autorun,
1553  &len) == ERROR_SUCCESS)
1554  {
1555  if (*autorun)
1556  ParseCommandLine(autorun);
1557  }
1558  RegCloseKey(hkey);
1559  }
1560 }
1561 
1562 /* Get the command that comes after a /C or /K switch */
1563 static VOID
1564 GetCmdLineCommand(TCHAR *commandline, TCHAR *ptr, BOOL AlwaysStrip)
1565 {
1566  TCHAR *LastQuote;
1567 
1568  while (_istspace(*ptr))
1569  ptr++;
1570 
1571  /* Remove leading quote, find final quote */
1572  if (*ptr == _T('"') &&
1573  (LastQuote = _tcsrchr(++ptr, _T('"'))) != NULL)
1574  {
1575  TCHAR *Space;
1576  /* Under certain circumstances, all quotes are preserved.
1577  * CMD /? documents these conditions as follows:
1578  * 1. No /S switch
1579  * 2. Exactly two quotes
1580  * 3. No "special characters" between the quotes
1581  * (CMD /? says &<>()@^| but parentheses did not
1582  * trigger this rule when I tested them.)
1583  * 4. Whitespace exists between the quotes
1584  * 5. Enclosed string is an executable filename
1585  */
1586  *LastQuote = _T('\0');
1587  for (Space = ptr + 1; Space < LastQuote; Space++)
1588  {
1589  if (_istspace(*Space)) /* Rule 4 */
1590  {
1591  if (!AlwaysStrip && /* Rule 1 */
1592  !_tcspbrk(ptr, _T("\"&<>@^|")) && /* Rules 2, 3 */
1593  SearchForExecutable(ptr, commandline)) /* Rule 5 */
1594  {
1595  /* All conditions met: preserve both the quotes */
1596  *LastQuote = _T('"');
1597  _tcscpy(commandline, ptr - 1);
1598  return;
1599  }
1600  break;
1601  }
1602  }
1603 
1604  /* The conditions were not met: remove both the
1605  * leading quote and the last quote */
1606  _tcscpy(commandline, ptr);
1607  _tcscpy(&commandline[LastQuote - ptr], LastQuote + 1);
1608  return;
1609  }
1610 
1611  /* No quotes; just copy */
1612  _tcscpy(commandline, ptr);
1613 }
1614 
1615 /*
1616  * set up global initializations and process parameters
1617  */
1618 static VOID
1620 {
1621  HMODULE NtDllModule;
1622  TCHAR commandline[CMDLINE_LENGTH];
1623  TCHAR ModuleName[_MAX_PATH + 1];
1624  INT nExitCode;
1625 
1626  //INT len;
1627  TCHAR *ptr, *cmdLine, option = 0;
1628  BOOL AlwaysStrip = FALSE;
1629  BOOL AutoRun = TRUE;
1630 
1631  /* Get version information */
1632  InitOSVersion();
1633 
1634  /* Some people like to run ReactOS cmd.exe on Win98, it helps in the
1635  * build process. So don't link implicitly against ntdll.dll, load it
1636  * dynamically instead */
1637  NtDllModule = GetModuleHandle(TEXT("ntdll.dll"));
1638  if (NtDllModule != NULL)
1639  {
1640  NtQueryInformationProcessPtr = (NtQueryInformationProcessProc)GetProcAddress(NtDllModule, "NtQueryInformationProcess");
1641  NtReadVirtualMemoryPtr = (NtReadVirtualMemoryProc)GetProcAddress(NtDllModule, "NtReadVirtualMemory");
1642  }
1643 
1644  InitLocale();
1645 
1646  /* get default input and output console handles */
1649 
1650  /* Initialize prompt support */
1651  InitPrompt();
1652 
1653 #ifdef FEATURE_DIR_STACK
1654  /* initialize directory stack */
1656 #endif
1657 
1658 #ifdef FEATURE_HISTORY
1659  /*initialize history*/
1660  InitHistory();
1661 #endif
1662 
1663  /* Set COMSPEC environment variable */
1664  if (0 != GetModuleFileName (NULL, ModuleName, _MAX_PATH + 1))
1665  {
1666  ModuleName[_MAX_PATH] = _T('\0');
1667  SetEnvironmentVariable (_T("COMSPEC"), ModuleName);
1668  }
1669 
1670  /* Add ctrl break handler */
1671  AddBreakHandler();
1672 
1673  /* Set our default console mode */
1674  SetConsoleMode(hOut, 0); // Reinitialize the console output mode
1677 
1678  cmdLine = GetCommandLine();
1679  TRACE ("[command args: %s]\n", debugstr_aw(cmdLine));
1680 
1681  for (ptr = cmdLine; *ptr; ptr++)
1682  {
1683  if (*ptr == _T('/'))
1684  {
1685  option = _totupper(ptr[1]);
1686  if (option == _T('?'))
1687  {
1689  nErrorLevel = 1;
1690  bExit = TRUE;
1691  return;
1692  }
1693  else if (option == _T('P'))
1694  {
1695  if (!IsExistingFile (_T("\\autoexec.bat")))
1696  {
1697 #ifdef INCLUDE_CMD_DATE
1698  cmd_date (_T(""));
1699 #endif
1700 #ifdef INCLUDE_CMD_TIME
1701  cmd_time (_T(""));
1702 #endif
1703  }
1704  else
1705  {
1706  ParseCommandLine (_T("\\autoexec.bat"));
1707  }
1708  bCanExit = FALSE;
1709  }
1710  else if (option == _T('A'))
1711  {
1713  }
1714  else if (option == _T('C') || option == _T('K') || option == _T('R'))
1715  {
1716  /* Remainder of command line is a command to be run */
1717  break;
1718  }
1719  else if (option == _T('D'))
1720  {
1721  AutoRun = FALSE;
1722  }
1723  else if (option == _T('Q'))
1724  {
1726  }
1727  else if (option == _T('S'))
1728  {
1729  AlwaysStrip = TRUE;
1730  }
1731 #ifdef INCLUDE_CMD_COLOR
1732  else if (!_tcsnicmp(ptr, _T("/T:"), 3))
1733  {
1734  /* process /T (color) argument */
1735  wDefColor = (WORD)_tcstoul(&ptr[3], &ptr, 16);
1737  }
1738 #endif
1739  else if (option == _T('U'))
1740  {
1741  bUnicodeOutput = TRUE;
1742  }
1743  else if (option == _T('V'))
1744  {
1745  bDelayedExpansion = _tcsnicmp(&ptr[2], _T(":OFF"), 4);
1746  }
1747  }
1748  }
1749 
1750  if (!*ptr)
1751  {
1752  /* If neither /C or /K was given, display a simple version string */
1753  ConOutChar(_T('\n'));
1755  _T(KERNEL_VERSION_STR),
1756  _T(KERNEL_VERSION_BUILD_STR));
1757  ConOutPuts(_T("(C) Copyright 1998-") _T(COPYRIGHT_YEAR) _T(" ReactOS Team.\n"));
1758  }
1759 
1760  if (AutoRun)
1761  {
1764  }
1765 
1766  if (*ptr)
1767  {
1768  /* Do the /C or /K command */
1769  GetCmdLineCommand(commandline, &ptr[2], AlwaysStrip);
1771  nExitCode = ParseCommandLine(commandline);
1773  if (option != _T('K'))
1774  {
1775  nErrorLevel = nExitCode;
1776  bExit = TRUE;
1777  }
1778  }
1779 }
1780 
1781 
1782 static VOID Cleanup()
1783 {
1784  /* run cmdexit.bat */
1785  if (IsExistingFile (_T("cmdexit.bat")))
1786  {
1788 
1789  ParseCommandLine (_T("cmdexit.bat"));
1790  }
1791  else if (IsExistingFile (_T("\\cmdexit.bat")))
1792  {
1794  ParseCommandLine (_T("\\cmdexit.bat"));
1795  }
1796 
1797 #ifdef FEATURE_DIRECTORY_STACK
1798  /* destroy directory stack */
1800 #endif
1801 
1802 #ifdef FEATURE_HISTORY
1803  CleanHistory();
1804 #endif
1805 
1806  /* free GetEnvVar's buffer */
1807  GetEnvVar(NULL);
1808 
1809  /* Remove ctrl break handler */
1811 
1812  /* Restore the default console mode */
1817 
1818  DeleteCriticalSection(&ChildProcessRunningLock);
1819 }
1820 
1821 /*
1822  * main function
1823  */
1824 int _tmain(int argc, const TCHAR *argv[])
1825 {
1826  HANDLE hConsole;
1827  TCHAR startPath[MAX_PATH];
1829 
1830  InitializeCriticalSection(&ChildProcessRunningLock);
1832 
1833  GetCurrentDirectory(MAX_PATH,startPath);
1834  _tchdir(startPath);
1835 
1836  SetFileApisToOEM();
1837  InputCodePage = 0;
1838  OutputCodePage = 0;
1839 
1840  hConsole = CreateFile(_T("CONOUT$"), GENERIC_READ|GENERIC_WRITE,
1842  OPEN_EXISTING, 0, NULL);
1843  if (hConsole != INVALID_HANDLE_VALUE)
1844  {
1845  if (!GetConsoleScreenBufferInfo(hConsole, &Info))
1846  {
1848  CloseHandle(hConsole);
1849  return(1);
1850  }
1851  wDefColor = Info.wAttributes;
1852  CloseHandle(hConsole);
1853  }
1854 
1858 
1859  /* check switches on command-line */
1860  Initialize();
1861 
1862  /* call prompt routine */
1863  ProcessInput();
1864 
1865  /* do the cleanup */
1866  Cleanup();
1867 
1869 
1871  return(nErrorLevel);
1872 }
1873 
1874 /* EOF */
VOID InitLocale(VOID)
Definition: locale.c:25
DWORD *typedef PVOID
Definition: winlogon.h:52
#define RegQueryValueEx
Definition: winreg.h:521
INT nErrorLevel
Definition: cmd.c:161
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:1255
Definition: cmd.h:363
VOID PrintCommandList(VOID)
Definition: cmdtable.c:245
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:80
BOOL CheckCtrlBreak(INT)
Definition: misc.c:132
#define cmd_exit(code)
Definition: cmddbg.h:34
unsigned short WORD
Definition: ntddk_ex.h:93
static LPTSTR GetEnhancedVar(TCHAR **pFormat, LPTSTR(*GetVar)(TCHAR, BOOL *))
Definition: cmd.c:846
const CHAR * LPCTSTR
Definition: xmlstorage.h:193
#define CloseHandle
Definition: compat.h:398
BOOL bUnicodeOutput
Definition: cmd.c:163
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:160
int _tmain(int argc, const TCHAR *argv[])
Definition: cmd.c:1824
VOID InitHistory(VOID)
Definition: history.c:132
WORD wVirtualScanCode
Definition: wincon.h:228
#define SHELLEXECUTETEXT
Definition: cmd.c:258
struct _PARSED_COMMAND * Subcommands
Definition: cmd.h:366
#define ERROR_SUCCESS
Definition: deptool.c:10
VOID CleanHistory(VOID)
Definition: history.c:151
#define BREAK_INPUT
Definition: cmd.h:39
BOOL bIgnoreEcho
Definition: cmd.c:159
#define LoadLibrary
Definition: winbase.h:3595
VOID ConErrResPuts(UINT resID)
Definition: console.c:476
#define _tcsicmp
Definition: xmlstorage.h:205
LPBATCH_CONTEXT bc
Definition: batch.c:66
LPCTSTR GetBatchVar(TCHAR *varName, UINT *varNameLen)
Definition: cmd.c:1095
Definition: ftp_var.h:139
#define SEE_MASK_NOCLOSEPROCESS
Definition: shellapi.h:31
#define KEY_READ
Definition: nt_native.h:1023
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:92
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:369
#define SEE_MASK_NO_CONSOLE
Definition: shellapi.h:38
#define HKEY_CURRENT_USER
Definition: winreg.h:11
#define STRING_MORE
Definition: resource.h:248
unsigned char * LPBYTE
Definition: typedefs.h:53
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
Definition: cmd.h:363
VOID DestroyDirectoryStack(VOID)
Definition: dirstack.c:90
#define debugstr_aw
Definition: precomp.h:34
COMMAND cmds[]
Definition: main.c:21
#define TRUE
Definition: numbers.c:17
#define CMDLINE_LENGTH
Definition: help.h:12
DWORD dwControlKeyState
Definition: wincon.h:233
HANDLE hIn
Definition: cmd.c:168
#define CTRL_C_EVENT
Definition: wincon.h:65
#define New(t)
Definition: rtf.h:1076
union _KEY_EVENT_RECORD::@2763 uChar
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:1041
$ULONG LowPart
Definition: ntbasedef.h:568
static VOID GetCmdLineCommand(TCHAR *commandline, TCHAR *ptr, BOOL AlwaysStrip)
Definition: cmd.c:1564
VOID ConErrFormatMessage(DWORD MessageId,...)
Definition: console.c:381
VOID ConOutResPaging(BOOL NewPage, UINT resID)
Definition: console.c:269
_In_ BOOL _In_ HANDLE hProcess
Definition: mapping.h:70
INT ParseCommandLine(LPTSTR cmd)
Definition: cmd.c:567
BOOL SubstituteVars(TCHAR *Src, TCHAR *Dest, TCHAR Delim)
Definition: cmd.c:1140
INT FormatDate(TCHAR *, LPSYSTEMTIME, BOOL)
Definition: dir.c:659
DWORD dwFlags
Definition: winbase.h:793
VOID InitPrompt(VOID)
Definition: prompt.c:57
VOID ConOutResPuts(UINT resID)
Definition: console.c:276
_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 FILE_SHARE_WRITE
Definition: nt_native.h:681
#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:173
int32_t INT
Definition: typedefs.h:57
DWORD DWORD
Definition: winlogon.h:75
static char ** argv
Definition: ServiceArgs.c:14
struct _PARSED_COMMAND * Next
Definition: cmd.h:367
CHAR * LPTSTR
Definition: xmlstorage.h:192
LPTSTR ReadBatchLine()
Definition: batch.c:442
#define FILE_SHARE_READ
Definition: compat.h:125
#define _itot
Definition: tchar.h:608
#define SearchPath
Definition: winbase.h:3633
WORD wVirtualKeyCode
Definition: wincon.h:227
static USHORT USHORT * NewLength
NTSTATUS(WINAPI * NtQueryInformationProcessProc)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG)
Definition: cmd.c:152
TCHAR firstvar
Definition: batch.h:27
Definition: cmd.h:363
#define ENABLE_ECHO_INPUT
Definition: wincon.h:77
BOOL SetScreenColor(WORD wColor, BOOL bNoFill)
Definition: color.c:27
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
GLenum const GLfloat * params
Definition: glext.h:5645
INT nNumberGroups
Definition: locale.c:22
LPCSTR filename
Definition: alphablend.c:63
#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:786
#define _MAX_PATH
Definition: utility.h:77
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, BOOL Add)
Definition: console.c:2111
#define GENERIC_WRITE
Definition: nt_native.h:90
#define NULL
Definition: mystdio.h:57
NTSTATUS(WINAPI * NtReadVirtualMemoryProc)(HANDLE, PVOID, PVOID, ULONG, PULONG)
Definition: cmd.c:154
LPTSTR FindArg(TCHAR Char, BOOL *IsParam0)
Definition: batch.c:83
#define KEY_EVENT
Definition: wincon.h:122
static PVOID ptr
Definition: dispmode.c:40
int ip[4]
Definition: rtl.c:1158
#define GetCurrentDirectory
Definition: winbase.h:3538
#define INT(a)
Definition: assyntax.h:463
UINT WINAPI DECLSPEC_HOTPATCH GetConsoleOutputCP(VOID)
Definition: console.c:2453
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
Definition: getopt.h:108
#define GetConsoleTitle
Definition: wincon.h:763
VOID error_out_of_memory(VOID)
Definition: error.c:135
#define HANDLE_FLAG_INHERIT
Definition: winbase.h:259
BOOL SearchForExecutable(LPCTSTR, LPTSTR)
Definition: where.c:142
static VOID ExecuteAutoRunFile(HKEY hkeyRoot)
Definition: cmd.c:1536
UINT WINAPI DECLSPEC_HOTPATCH GetConsoleCP(VOID)
Definition: console.c:2393
#define GetCommandLine
Definition: winbase.h:3532
BOOL WINAPI BreakHandler(DWORD dwCtrlType)
Definition: cmd.c:1435
#define FindFirstFile
Definition: winbase.h:3515
#define STARTF_USESHOWWINDOW
Definition: winbase.h:463
#define STD_INPUT_HANDLE
Definition: winbase.h:262
DWORD dwChildProcessId
Definition: cmd.c:167
INT cmd_time(LPTSTR)
Definition: time.c:132
static VOID Initialize()
Definition: cmd.c:1619
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
#define OPEN_EXISTING
Definition: compat.h:426
INT DoCommand(LPTSTR first, LPTSTR rest, PARSED_COMMAND *Cmd)
Definition: cmd.c:498
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
UINTN Size
Definition: acefiex.h:550
LPTSTR DuplicateEnvironment(VOID)
Definition: setlocal.c:21
#define APPEND(From, Length)
char TCHAR
Definition: xmlstorage.h:189
#define STRING_CMD_HELP2
Definition: resource.h:81
BOOL bCanExit
Definition: cmd.c:157
BOOL WINAPI GetConsoleScreenBufferInfo(IN HANDLE hConsoleOutput, OUT PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo)
Definition: console.c:420
_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
VOID ConOutResPrintf(UINT resID,...)
Definition: console.c:439
#define STRING_CMD_HELP4
Definition: resource.h:83
VOID InitDirectoryStack(VOID)
Definition: dirstack.c:79
TCHAR BatchFilePath[MAX_PATH]
Definition: batch.h:14
static NtReadVirtualMemoryProc NtReadVirtualMemoryPtr
Definition: cmd.c:174
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
LPCSTR lpParameters
Definition: shellapi.h:291
HANDLE HKEY
Definition: registry.h:24
uint64_t ULONGLONG
Definition: typedefs.h:66
GLfloat param
Definition: glext.h:5796
#define MAX_PATH
Definition: compat.h:26
LPTSTR lpOriginalEnvironment
Definition: cmd.c:170
static VOID ExecutePipeline(PARSED_COMMAND *Cmd)
Definition: cmd.c:619
BOOL(CALLBACK * PHANDLER_ROUTINE)(_In_ DWORD)
Definition: wincon.h:222
BOOL bDisableBatchEcho
Definition: cmd.c:164
KEY_EVENT_RECORD KeyEvent
Definition: wincon.h:263
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
LPTSTR DoDelayedExpansion(LPTSTR Line)
Definition: cmd.c:1342
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
UINT OutputCodePage
Definition: console.c:26
#define GetModuleFileName
Definition: winbase.h:3564
Definition: cmd.h:363
int(* FARPROC)()
Definition: compat.h:28
#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:84
BOOL ReadLine(TCHAR *commandline, BOOL bMore)
Definition: cmd.c:1369
Definition: ncftp.h:79
UINT InputCodePage
Definition: console.c:25
struct _PARSED_COMMAND::@28::@30 Command
#define FILE_ATTRIBUTE_ARCHIVE
Definition: nt_native.h:706
Definition: cmd.h:363
#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:1293
int ret
LPTSTR GetDateString(VOID)
Definition: locale.c:58
static VOID ProcessInput()
Definition: cmd.c:1416
#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:585
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define GetFullPathName
Definition: winbase.h:3554
PBYTE Character
Definition: device.h:83
VOID UndoRedirection(REDIRECTION *, REDIRECTION *End)
Definition: redir.c:133
GLenum GLsizei len
Definition: glext.h:6722
static VOID Cleanup()
Definition: cmd.c:1782
#define SetEnvironmentVariable
Definition: winbase.h:3641
Definition: cmd.h:363
#define GENERIC_READ
Definition: compat.h:124
#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
union _INPUT_RECORD::@2764 Event
#define CreateProcess
Definition: winbase.h:3491
VOID AddBreakHandler(VOID)
Definition: cmd.c:1489
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
UINTN UINT8 Value
Definition: acefiex.h:725
Status
Definition: gdiplustypes.h:24
struct _REDIRECTION * Redirections
Definition: cmd.h:368
VOID error_too_many_parameters(LPTSTR)
Definition: error.c:76
#define ENABLE_PROCESSED_OUTPUT
Definition: blue.h:44
#define STRING_CMD_HELP3
Definition: resource.h:82
TCHAR * Unparse(PARSED_COMMAND *Cmd, TCHAR *Out, TCHAR *OutEnd)
Definition: parser.c:844
BOOL SubstituteForVars(TCHAR *Src, TCHAR *Dest)
Definition: cmd.c:1306
VOID WINAPI SetFileApisToOEM(VOID)
Definition: utils.c:819
#define _stprintf
Definition: utility.h:124
#define ENABLE_PROCESSED_INPUT
Definition: wincon.h:75
VOID error_syntax(LPTSTR)
Definition: error.c:149
#define cmd_alloc(size)
Definition: cmddbg.h:29
#define NT_SUCCESS(StatCode)
Definition: cmd.c:149
#define RegOpenKeyEx
Definition: winreg.h:517
#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
Definition: ntddk_ex.h:242
#define GetModuleHandle
Definition: winbase.h:3560
STARTUPINFOA STARTUPINFO
Definition: winbase.h:3452
static INT Execute(LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
Definition: cmd.c:314
#define SetConsoleTitle
Definition: wincon.h:771
VOID error_bad_command(LPTSTR)
Definition: error.c:121
unsigned char dummy
Definition: maze.c:118
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
LPTSTR GetEnvVar(LPCTSTR varName)
Definition: cmd.c:768
BOOL bDelayedExpansion
Definition: cmd.c:165
#define cmd_dup(str)
Definition: cmddbg.h:32
VOID ConOutPuts(LPTSTR)
Definition: console.c:283
#define FILE_ATTRIBUTE_HIDDEN
Definition: nt_native.h:703
unsigned int * PULONG
Definition: retypes.h:1
#define STRING_CMD_HELP8
Definition: resource.h:87
#define min(a, b)
Definition: monoChain.cc:55
CRITICAL_SECTION ChildProcessRunningLock
Definition: cmd.c:162
unsigned int UINT
Definition: ndis.h:50
WORD wShowWindow
Definition: winbase.h:794
BOOL PerformRedirection(REDIRECTION *)
Definition: redir.c:54
#define CreateFile
Definition: winbase.h:3482
HANDLE CMD_ModuleHandle
Definition: cmd.c:171
BOOL bExit
Definition: cmd.c:156
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:1195
#define STRING_FREE_ERROR1
Definition: resource.h:52
WORD EventType
Definition: wincon.h:261
Definition: cmd.h:363
HANDLE HMODULE
Definition: typedefs.h:76
INT ExecuteCommand(PARSED_COMMAND *Cmd)
Definition: cmd.c:706
HANDLE hOut
Definition: cmd.c:169
_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
#define FALSE
Definition: numbers.c:16
enum _PROCESSINFOCLASS PROCESSINFOCLASS
Definition: loader.c:59
#define _istspace
Definition: tchar.h:1504
unsigned int ULONG
Definition: retypes.h:1
VOID error_no_pipe(VOID)
Definition: error.c:128
INT ExecuteIf(struct _PARSED_COMMAND *Cmd)
Definition: if.c:66
LPSTR name
Definition: cmdcons.c:27
#define GetEnvironmentVariable
Definition: winbase.h:3547
#define GetProcAddress(x, y)
Definition: compat.h:410
#define STRING_CMD_ERROR5
Definition: resource.h:33
#define STRING_CMD_HELP7
Definition: resource.h:86
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
BOOL bTitleSet
Definition: cmd.c:166
#define max(a, b)
Definition: slicer.cc:81
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define INFINITE
Definition: serial.h:102
VOID ConOutChar(TCHAR)
Definition: console.c:259
#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
#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
#define SetCurrentDirectory
Definition: winbase.h:3636
#define STRING_CMD_HELP6
Definition: resource.h:85
#define FILE_ATTRIBUTE_OFFLINE
Definition: nt_native.h:712
ULONG ImageSubsystem
Definition: ntddk_ex.h:308
VOID RemoveBreakHandler(VOID)
Definition: cmd.c:1495
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
BOOL bCtrlBreak
Definition: cmd.c:158
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:500