* 12-Jul-2004 (Jens Collin <jens.collin@lakhei.com>)
* Added ShellExecute call when all else fails to be able to "launch" any file.
*
- * 02-Apr-2005 (Magnus Olsen) <magnus@greatlord.com>)
- * Remove all hardcode string to En.rc
+ * 02-Apr-2005 (Magnus Olsen <magnus@greatlord.com>)
+ * Remove all hardcode string to En.rc
+ *
+ * 06-May-2005 (Klemens Friedl <frik85@gmail.com>)
+ * Add 'help' command (list all commands plus description)
+ *
+ * 06-jul-2005 (Magnus Olsen <magnus@greatlord.com>)
+ * translate '%errorlevel%' to the internal value.
+ * Add proper memmory alloc ProcessInput, the error
+ * handling for memmory handling need to be improve
*/
-#include "precomp.h"
+#include <precomp.h>
+#include <malloc.h>
#include "resource.h"
#ifndef NT_SUCCESS
#define NT_SUCCESS(StatCode) ((NTSTATUS)(StatCode) >= 0)
#endif
-typedef NTSTATUS (STDCALL *NtQueryInformationProcessProc)(HANDLE, PROCESSINFOCLASS,
+typedef NTSTATUS (WINAPI *NtQueryInformationProcessProc)(HANDLE, PROCESSINFOCLASS,
PVOID, ULONG, PULONG);
-typedef NTSTATUS (STDCALL *NtReadVirtualMemoryProc)(HANDLE, PVOID, PVOID, ULONG, PULONG);
+typedef NTSTATUS (WINAPI *NtReadVirtualMemoryProc)(HANDLE, PVOID, PVOID, ULONG, PULONG);
BOOL bExit = FALSE; /* indicates EXIT was typed */
BOOL bCanExit = TRUE; /* indicates if this shell is exitable */
HANDLE hIn;
HANDLE hOut;
HANDLE hConsole;
+HANDLE CMD_ModuleHandle;
+HMODULE NtDllModule;
-static NtQueryInformationProcessProc NtQueryInformationProcessPtr;
-static NtReadVirtualMemoryProc NtReadVirtualMemoryPtr;
-static BOOL NtDllChecked = FALSE;
+static NtQueryInformationProcessProc NtQueryInformationProcessPtr = NULL;
+static NtReadVirtualMemoryProc NtReadVirtualMemoryPtr = NULL;
#ifdef INCLUDE_CMD_COLOR
WORD wColor; /* current color */
#endif
/*
- * is character a delimeter when used on first word?
+ * convert
*
+ * insert commas into a number
*/
+INT
+ConvertULargeInteger (ULARGE_INTEGER num, LPTSTR des, INT len, BOOL bPutSeperator)
+{
+ TCHAR temp[32];
+ INT c = 0;
+ INT n = 0;
+ if (num.QuadPart == 0)
+ {
+ des[0] = _T('0');
+ des[1] = _T('\0');
+ n = 1;
+ }
+ else
+ {
+ temp[31] = 0;
+ while (num.QuadPart > 0)
+ {
+ if ((((c + 1) % (nNumberGroups + 1)) == 0) && (bPutSeperator))
+ temp[30 - c++] = cThousandSeparator;
+ temp[30 - c++] = (TCHAR)(num.QuadPart % 10) + _T('0');
+ num.QuadPart /= 10;
+ }
+
+ for (n = 0; n <= c; n++)
+ des[n] = temp[31 - c + n];
+ }
+
+ return n;
+}
+
+/*
+ * is character a delimeter when used on first word?
+ *
+ */
static BOOL IsDelimiter (TCHAR c)
{
return (c == _T('/') || c == _T('=') || c == _T('\0') || _istspace (c));
PROCESS_BASIC_INFORMATION Info;
PEB ProcessPeb;
ULONG BytesRead;
- HMODULE NtDllModule;
-
- /* Some people like to run ReactOS cmd.exe on Win98, it helps in the
- build process. So don't link implicitly against ntdll.dll, load it
- dynamically instead */
- if (! NtDllChecked)
- {
- NtDllChecked = TRUE;
- NtDllModule = LoadLibrary(_T("ntdll.dll"));
- if (NULL == NtDllModule)
- {
- /* Probably non-WinNT system. Just wait for the commands
- to finish. */
- NtQueryInformationProcessPtr = NULL;
- NtReadVirtualMemoryPtr = NULL;
- return TRUE;
- }
- NtQueryInformationProcessPtr = (NtQueryInformationProcessProc)
- GetProcAddress(NtDllModule, "NtQueryInformationProcess");
- NtReadVirtualMemoryPtr = (NtReadVirtualMemoryProc)
- GetProcAddress(NtDllModule, "NtReadVirtualMemory");
- }
if (NULL == NtQueryInformationProcessPtr || NULL == NtReadVirtualMemoryPtr)
{
return TRUE;
}
- Status = NtQueryInformationProcessPtr(Process, ProcessBasicInformation,
- &Info, sizeof(PROCESS_BASIC_INFORMATION), NULL);
+ Status = NtQueryInformationProcessPtr (
+ Process, ProcessBasicInformation,
+ &Info, sizeof(PROCESS_BASIC_INFORMATION), NULL);
if (! NT_SUCCESS(Status))
{
#ifdef _DEBUG
#endif
return TRUE;
}
- Status = NtReadVirtualMemoryPtr(Process, Info.PebBaseAddress, &ProcessPeb,
- sizeof(PEB), &BytesRead);
+ Status = NtReadVirtualMemoryPtr (
+ Process, Info.PebBaseAddress, &ProcessPeb,
+ sizeof(PEB), &BytesRead);
if (! NT_SUCCESS(Status) || sizeof(PEB) != BytesRead)
{
#ifdef _DEBUG
#endif
typedef HINSTANCE (WINAPI *MYEX)(
- HWND hwnd,
- LPCTSTR lpOperation,
- LPCTSTR lpFile,
- LPCTSTR lpParameters,
- LPCTSTR lpDirectory,
- INT nShowCmd
+ HWND hwnd,
+ LPCTSTR lpOperation,
+ LPCTSTR lpFile,
+ LPCTSTR lpParameters,
+ LPCTSTR lpDirectory,
+ INT nShowCmd
);
static BOOL RunFile(LPTSTR filename)
{
- HMODULE hShell32;
- MYEX hShExt;
- HINSTANCE ret;
+ HMODULE hShell32;
+ MYEX hShExt;
+ HINSTANCE ret;
#ifdef _DEBUG
- DebugPrintf (_T("RunFile(%s)\n"), filename);
+ DebugPrintf (_T("RunFile(%s)\n"), filename);
#endif
hShell32 = LoadLibrary(_T("SHELL32.DLL"));
if (!hShell32)
/*
* This command (in first) was not found in the command table
*
- * first - first word on command line
- * rest - rest of command line
+ * Full - whole command line
+ * First - first word on command line
+ * Rest - rest of command line
*/
static VOID
-Execute (LPTSTR full, LPTSTR first, LPTSTR rest)
+Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest)
{
- TCHAR szFullName[MAX_PATH];
-#ifndef __REACTOS__
+ TCHAR *szFullName=NULL;
+ TCHAR *first = NULL;
+ TCHAR *rest = NULL;
+ TCHAR *full = NULL;
+ TCHAR *dot = NULL;
TCHAR szWindowTitle[MAX_PATH];
-#endif
DWORD dwExitCode = 0;
#ifdef _DEBUG
DebugPrintf (_T("Execute: \'%s\' \'%s\'\n"), first, rest);
#endif
+ /* we need biger buffer that First, Rest, Full are already
+ need rewrite some code to use realloc when it need instead
+ of add 512bytes extra */
+
+ first = malloc ( (_tcslen(First) + 512) * sizeof(TCHAR));
+ if (first == NULL)
+ {
+ error_out_of_memory();
+ return ;
+ }
+
+ rest = malloc ( (_tcslen(Rest) + 512) * sizeof(TCHAR));
+ if (rest == NULL)
+ {
+ free (first);
+ error_out_of_memory();
+ return ;
+ }
+
+ full = malloc ( (_tcslen(Full) + 512) * sizeof(TCHAR));
+ if (full == NULL)
+ {
+ free (first);
+ free (rest);
+ error_out_of_memory();
+ return ;
+ }
+
+ szFullName = malloc ( (_tcslen(Full) + 512) * sizeof(TCHAR));
+ if (full == NULL)
+ {
+ free (first);
+ free (rest);
+ free (full);
+ error_out_of_memory();
+ return ;
+ }
+
+
+ /* Though it was already parsed once, we have a different set of rules
+ for parsing before we pass to CreateProccess */
+ if(!_tcschr(Full,_T('\"')))
+ {
+ _tcscpy(first,First);
+ _tcscpy(rest,Rest);
+ _tcscpy(full,Full);
+ }
+ else
+ {
+ UINT i = 0;
+ BOOL bInside = FALSE;
+ rest[0] = _T('\0');
+ full[0] = _T('\0');
+ first[0] = _T('\0');
+ _tcscpy(first,Full);
+ /* find the end of the command and start of the args */
+ for(i = 0; i < _tcslen(first); i++)
+ {
+ if(!_tcsncmp(&first[i], _T("\""), 1))
+ bInside = !bInside;
+ if(!_tcsncmp(&first[i], _T(" "), 1) && !bInside)
+ {
+ _tcscpy(rest,&first[i]);
+ first[i] = _T('\0');
+ break;
+ }
+
+ }
+ i = 0;
+ /* remove any slashes */
+ while(i < _tcslen(first))
+ {
+ if(first[i] == _T('\"'))
+ memmove(&first[i],&first[i + 1], _tcslen(&first[i]) * sizeof(TCHAR));
+ else
+ i++;
+ }
+ /* Drop quotes around it just in case there is a space */
+ _tcscpy(full,_T("\""));
+ _tcscat(full,first);
+ _tcscat(full,_T("\" "));
+ _tcscat(full,rest);
+ }
+
/* check for a drive change */
if ((_istalpha (first[0])) && (!_tcscmp (first + 1, _T(":"))))
{
working = SetCurrentDirectory(str);
}
- if (!working) ConErrPuts (INVALIDDRIVE);
+ if (!working) ConErrResPuts (STRING_FREE_ERROR1);
+
+ free (first);
+ free (rest);
+ free (full);
+ free (szFullName);
return;
}
/* search the PATH environment variable for the binary */
if (!SearchForExecutable (first, szFullName))
{
- error_bad_command ();
- return;
+ error_bad_command ();
+ free (first);
+ free (rest);
+ free (full);
+ free (szFullName);
+ return;
+
}
-#ifndef __REACTOS__
GetConsoleTitle (szWindowTitle, MAX_PATH);
-#endif
/* check if this is a .BAT or .CMD file */
- if (!_tcsicmp (_tcsrchr (szFullName, _T('.')), _T(".bat")) ||
- !_tcsicmp (_tcsrchr (szFullName, _T('.')), _T(".cmd")))
+ dot = _tcsrchr (szFullName, _T('.'));
+ if (dot && (!_tcsicmp (dot, _T(".bat")) || !_tcsicmp (dot, _T(".cmd"))))
{
#ifdef _DEBUG
DebugPrintf (_T("[BATCH: %s %s]\n"), szFullName, rest);
NULL,
NULL,
TRUE,
- CREATE_NEW_PROCESS_GROUP,
+ 0, /* CREATE_NEW_PROCESS_GROUP */
NULL,
NULL,
&stui,
&prci))
+
{
if (IsConsoleProcess(prci.hProcess))
{
}
}
// restore console mode
- SetConsoleMode( GetStdHandle( STD_INPUT_HANDLE ),
- ENABLE_PROCESSED_INPUT );
+ SetConsoleMode (
+ GetStdHandle( STD_INPUT_HANDLE ),
+ ENABLE_PROCESSED_INPUT );
}
-#ifndef __REACTOS__
+ /* Get code page if it has been change */
+ InputCodePage= GetConsoleCP();
+ OutputCodePage = GetConsoleOutputCP();
SetConsoleTitle (szWindowTitle);
-#endif
+
+ free(first);
+ free(rest);
+ free(full);
+ free (szFullName);
}
static VOID
DoCommand (LPTSTR line)
{
- TCHAR com[CMDLINE_LENGTH]; /* the first word in the command */
- LPTSTR cp = com;
+ TCHAR *com = NULL; /* the first word in the command */
+ TCHAR *cp = NULL;
LPTSTR cstart;
LPTSTR rest; /* pointer to the rest of the command line */
INT cl;
DebugPrintf (_T("DoCommand: (\'%s\')\n"), line);
#endif /* DEBUG */
+ com = malloc( (_tcslen(line) +512)*sizeof(TCHAR) );
+ if (com == NULL)
+ {
+ error_out_of_memory();
+ return;
+ }
+
+ cp = com;
/* Skip over initial white space */
while (_istspace (*line))
line++;
/* Terminate first word */
*cp = _T('\0');
- /* commands are limited to MAX_PATH */
+ /* Do not limit commands to MAX_PATH */
+ /*
if(_tcslen(com) > MAX_PATH)
{
- error_bad_command();
- return;
+ error_bad_command();
+ free(com);
+ return;
}
+ */
- /* Skip over whitespace to rest of line */
- while (_istspace (*rest))
+ /* Skip over whitespace to rest of line, exclude 'echo' command */
+ if (_tcsicmp (com, _T("echo")))
+ {
+ while (_istspace (*rest))
rest++;
+ }
/* Scan internal command table */
for (cmdptr = cmds;; cmdptr++)
}
}
}
+ /* Just in case a CTRL+C slipped through a command */
+ bCtrlBreak = FALSE;
+ free(com);
}
INT nRedirFlags = 0;
INT Length;
UINT Attributes;
-
+ BOOL bNewBatch = TRUE;
HANDLE hOldConIn;
HANDLE hOldConOut;
HANDLE hOldConErr;
;
_tcscpy (err, t);
+ if(bc && !_tcslen (in) && _tcslen (bc->In))
+ _tcscpy(in, bc->In);
+ if(bc && !out[0] && _tcslen(bc->Out))
+ {
+ nRedirFlags |= OUTPUT_APPEND;
+ _tcscpy(out, bc->Out);
+ }
+ if(bc && !_tcslen (err) && _tcslen (bc->Err))
+ {
+ nRedirFlags |= ERROR_APPEND;
+ _tcscpy(err, bc->Err);
+ }
+
+
/* Set up the initial conditions ... */
/* preserve STDIN, STDOUT and STDERR handles */
hOldConIn = GetStdHandle (STD_INPUT_HANDLE);
HANDLE hFile;
SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
+ /* we need make sure the LastError msg is zero before calling CreateFile */
+ SetLastError(0);
+
+ /* Set up pipe for the standard input handler */
hFile = CreateFile (in, GENERIC_READ, FILE_SHARE_READ, &sa, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
- LoadString(GetModuleHandle(NULL), STRING_CMD_ERROR1, szMsg, RC_STRING_MAX_SIZE);
+ LoadString(CMD_ModuleHandle, STRING_CMD_ERROR1, szMsg, RC_STRING_MAX_SIZE);
ConErrPrintf(szMsg, in);
return;
}
if (!SetStdHandle (STD_INPUT_HANDLE, hFile))
{
- LoadString(GetModuleHandle(NULL), STRING_CMD_ERROR1, szMsg, RC_STRING_MAX_SIZE);
+ LoadString(CMD_ModuleHandle, STRING_CMD_ERROR1, szMsg, RC_STRING_MAX_SIZE);
ConErrPrintf(szMsg, in);
return;
}
/* Create unique temporary file name */
GetTempFileName (szTempPath, _T("CMD"), 0, szFileName[1]);
+ /* we need make sure the LastError msg is zero before calling CreateFile */
+ SetLastError(0);
+
/* Set current stdout to temporary file */
hFile[1] = CreateFile (szFileName[1], GENERIC_WRITE, 0, &sa,
TRUNCATE_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL);
+
if (hFile[1] == INVALID_HANDLE_VALUE)
{
- LoadString(GetModuleHandle(NULL), STRING_CMD_ERROR2, szMsg, RC_STRING_MAX_SIZE);
+ LoadString(CMD_ModuleHandle, STRING_CMD_ERROR2, szMsg, RC_STRING_MAX_SIZE);
ConErrPrintf(szMsg);
return;
}
_tcscpy (szFileName[0], szFileName[1]);
*szFileName[1] = _T('\0');
+ /* we need make sure the LastError msg is zero before calling CreateFile */
+ SetLastError(0);
+
/* open new stdin file */
hFile[0] = CreateFile (szFileName[0], GENERIC_READ, 0, &sa,
OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL);
HANDLE hFile;
SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
- hFile = CreateFile (out, GENERIC_WRITE, FILE_SHARE_READ, &sa,
+ /* we need make sure the LastError msg is zero before calling CreateFile */
+ SetLastError(0);
+
+ hFile = CreateFile (out, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, &sa,
(nRedirFlags & OUTPUT_APPEND) ? OPEN_ALWAYS : CREATE_ALWAYS,
- FILE_ATTRIBUTE_NORMAL, NULL);
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL);
+
if (hFile == INVALID_HANDLE_VALUE)
{
- LoadString(GetModuleHandle(NULL), STRING_CMD_ERROR3, szMsg, RC_STRING_MAX_SIZE);
- ConErrPrintf(szMsg, out);
- return;
+ INT size = _tcslen(out)-1;
+
+ if (out[size] != _T(':'))
+ {
+ LoadString(CMD_ModuleHandle, STRING_CMD_ERROR3, szMsg, RC_STRING_MAX_SIZE);
+ ConErrPrintf(szMsg, out);
+ return;
+ }
+
+ out[size]=_T('\0');
+ hFile = CreateFile (out, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, &sa,
+ (nRedirFlags & OUTPUT_APPEND) ? OPEN_ALWAYS : CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL);
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ LoadString(CMD_ModuleHandle, STRING_CMD_ERROR3, szMsg, RC_STRING_MAX_SIZE);
+ ConErrPrintf(szMsg, out);
+ return;
+ }
+
}
if (!SetStdHandle (STD_OUTPUT_HANDLE, hFile))
{
- LoadString(GetModuleHandle(NULL), STRING_CMD_ERROR3, szMsg, RC_STRING_MAX_SIZE);
+ LoadString(CMD_ModuleHandle, STRING_CMD_ERROR3, szMsg, RC_STRING_MAX_SIZE);
ConErrPrintf(szMsg, out);
return;
}
{
hFile = CreateFile (err,
GENERIC_WRITE,
- 0,
+ FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
&sa,
(nRedirFlags & ERROR_APPEND) ? OPEN_ALWAYS : CREATE_ALWAYS,
- FILE_ATTRIBUTE_NORMAL,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
- LoadString(GetModuleHandle(NULL), STRING_CMD_ERROR3, szMsg, RC_STRING_MAX_SIZE);
+ LoadString(CMD_ModuleHandle, STRING_CMD_ERROR3, szMsg, RC_STRING_MAX_SIZE);
ConErrPrintf(szMsg, err);
return;
}
if (!SetStdHandle (STD_ERROR_HANDLE, hFile))
{
- LoadString(GetModuleHandle(NULL), STRING_CMD_ERROR3, szMsg, RC_STRING_MAX_SIZE);
+ LoadString(CMD_ModuleHandle, STRING_CMD_ERROR3, szMsg, RC_STRING_MAX_SIZE);
ConErrPrintf(szMsg, err);
return;
}
CloseHandle (hErr);
hOldConErr = INVALID_HANDLE_VALUE;
}
+
+ if(bc)
+ bNewBatch = FALSE;
#endif
/* process final command */
DoCommand (s);
#ifdef FEATURE_REDIRECTION
+ if(bNewBatch && bc)
+ AddBatchRedirection(in, out, err);
/* close old stdin file */
#if 0 /* buggy implementation */
SetStdHandle (STD_INPUT_HANDLE, hOldConIn);
#endif /* FEATURE_REDIRECTION */
}
+BOOL
+GrowIfNecessary ( UINT needed, LPTSTR* ret, UINT* retlen )
+{
+ if ( *ret && needed < *retlen )
+ return TRUE;
+ *retlen = needed;
+ if ( *ret )
+ free ( *ret );
+ *ret = (LPTSTR)malloc ( *retlen * sizeof(TCHAR) );
+ if ( !*ret )
+ SetLastError ( ERROR_OUTOFMEMORY );
+ return *ret != NULL;
+}
+
+LPCTSTR
+GetEnvVarOrSpecial ( LPCTSTR varName )
+{
+ static LPTSTR ret = NULL;
+ static UINT retlen = 0;
+ UINT size;
+
+ size = GetEnvironmentVariable ( varName, ret, retlen );
+ if ( size > retlen )
+ {
+ if ( !GrowIfNecessary ( size, &ret, &retlen ) )
+ return NULL;
+ size = GetEnvironmentVariable ( varName, ret, retlen );
+ }
+ if ( size )
+ return ret;
+
+ /* env var doesn't exist, look for a "special" one */
+ /* %CD% */
+ if (_tcsicmp(varName,_T("cd")) ==0)
+ {
+ size = GetCurrentDirectory ( retlen, ret );
+ if ( size > retlen )
+ {
+ if ( !GrowIfNecessary ( size, &ret, &retlen ) )
+ return NULL;
+ size = GetCurrentDirectory ( retlen, ret );
+ }
+ if ( !size )
+ return NULL;
+ return ret;
+ }
+ /* %TIME% */
+ else if (_tcsicmp(varName,_T("time")) ==0)
+ {
+ SYSTEMTIME t;
+ if ( !GrowIfNecessary ( MAX_PATH, &ret, &retlen ) )
+ return NULL;
+ GetSystemTime(&t);
+ _sntprintf ( ret, retlen, _T("%02d%c%02d%c%02d%c%02d"),
+ t.wHour, cTimeSeparator, t.wMinute, cTimeSeparator,
+ t.wSecond, cDecimalSeparator, t.wMilliseconds );
+ return ret;
+ }
+ /* %DATE% */
+ else if (_tcsicmp(varName,_T("date")) ==0)
+ {
+ LPTSTR tmp;
+
+ if ( !GrowIfNecessary ( MAX_PATH, &ret, &retlen ) )
+ return NULL;
+ size = GetDateFormat(LOCALE_USER_DEFAULT, 0, NULL, _T("ddd"), ret, retlen );
+ /* TODO FIXME - test whether GetDateFormat() can return a value indicating the buffer wasn't big enough */
+ if ( !size )
+ return NULL;
+ tmp = ret + _tcslen(ret);
+ *tmp++ = _T(' ');
+ size = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, tmp, retlen-(tmp-ret));
+ /* TODO FIXME - test whether GetDateFormat() can return a value indicating the buffer wasn't big enough */
+ if ( !size )
+ return NULL;
+ return ret;
+ }
+
+ /* %RANDOM% */
+ else if (_tcsicmp(varName,_T("random")) ==0)
+ {
+ if ( !GrowIfNecessary ( MAX_PATH, &ret, &retlen ) )
+ return NULL;
+ /* Get random number */
+ _itot(rand(),ret,10);
+ return ret;
+ }
+
+ /* %CMDCMDLINE% */
+ else if (_tcsicmp(varName,_T("cmdcmdline")) ==0)
+ {
+ return GetCommandLine();
+ }
+
+ /* %CMDEXTVERSION% */
+ else if (_tcsicmp(varName,_T("cmdextversion")) ==0)
+ {
+ if ( !GrowIfNecessary ( MAX_PATH, &ret, &retlen ) )
+ return NULL;
+ /* Set version number to 2 */
+ _itot(2,ret,10);
+ return ret;
+ }
+
+ /* %ERRORLEVEL% */
+ else if (_tcsicmp(varName,_T("errorlevel")) ==0)
+ {
+ if ( !GrowIfNecessary ( MAX_PATH, &ret, &retlen ) )
+ return NULL;
+ _itot(nErrorLevel,ret,10);
+ return ret;
+ }
+
+ GrowIfNecessary(_tcslen(varName) + 2, &ret, &retlen);
+ _stprintf(ret,_T("%%%s%%"),varName);
+ return ret; /* not found - return orginal string */
+}
+
+LPCTSTR
+GetParsedEnvVar ( LPCTSTR varName, UINT* varNameLen, BOOL ModeSetA )
+{
+ static LPTSTR ret = NULL;
+ static UINT retlen = 0;
+ LPTSTR p, tmp;
+ UINT size;
+
+ if ( varNameLen )
+ *varNameLen = 0;
+ SetLastError(0);
+ if ( *varName++ != '%' )
+ return NULL;
+ switch ( *varName )
+ {
+ case _T('0'):
+ case _T('1'):
+ case _T('2'):
+ case _T('3'):
+ case _T('4'):
+ case _T('5'):
+ case _T('6'):
+ case _T('7'):
+ case _T('8'):
+ case _T('9'):
+ if ((tmp = FindArg (*varName - _T('0'))))
+ {
+ if ( varNameLen )
+ *varNameLen = 2;
+ if ( !*tmp )
+ return _T("");
+ if ( !GrowIfNecessary ( _tcslen(tmp)+1, &ret, &retlen ) )
+ return NULL;
+ _tcscpy ( ret, tmp );
+ return ret;
+ }
+ if ( !GrowIfNecessary ( 3, &ret, &retlen ) )
+ return NULL;
+ ret[0] = _T('%');
+ ret[1] = *varName;
+ ret[2] = 0;
+ if ( varNameLen )
+ *varNameLen = 2;
+ return ret;
+
+ case _T('%'):
+ if ( !GrowIfNecessary ( 2, &ret, &retlen ) )
+ return NULL;
+ ret[0] = _T('%');
+ ret[1] = 0;
+ if ( varNameLen )
+ *varNameLen = 2;
+ return ret;
+
+ case _T('?'):
+ /* TODO FIXME 10 is only max size for 32-bit */
+ if ( !GrowIfNecessary ( 11, &ret, &retlen ) )
+ return NULL;
+ _sntprintf ( ret, retlen, _T("%u"), nErrorLevel);
+ ret[retlen-1] = 0;
+ if ( varNameLen )
+ *varNameLen = 2;
+ return ret;
+ }
+ if ( ModeSetA )
+ {
+ /* HACK for set/a */
+ if ( !GrowIfNecessary ( 2, &ret, &retlen ) )
+ return NULL;
+ ret[0] = _T('%');
+ ret[1] = 0;
+ if ( varNameLen )
+ *varNameLen = 1;
+ return ret;
+ }
+ p = _tcschr ( varName, _T('%') );
+ if ( !p )
+ {
+ SetLastError ( ERROR_INVALID_PARAMETER );
+ return NULL;
+ }
+ size = p-varName;
+ if ( varNameLen )
+ *varNameLen = size + 2;
+ p = alloca ( (size+1) * sizeof(TCHAR) );
+ memmove ( p, varName, size * sizeof(TCHAR) );
+ p[size] = 0;
+ varName = p;
+ return GetEnvVarOrSpecial ( varName );
+}
+
/*
* do the prompt/input/process loop
{
TCHAR commandline[CMDLINE_LENGTH];
TCHAR readline[CMDLINE_LENGTH];
- LPTSTR tp = NULL;
LPTSTR ip;
LPTSTR cp;
+ LPCTSTR tmp;
BOOL bEchoThisLine;
-
+ BOOL bModeSetA;
+ BOOL bIsBatch;
do
{
ReadCommand (readline, CMDLINE_LENGTH);
ip = readline;
bEchoThisLine = FALSE;
+ bIsBatch = FALSE;
}
+ else
+ {
+ bIsBatch = TRUE;
+ }
+
+ /* skip leading blanks */
+ while ( _istspace(*ip) )
+ ++ip;
cp = commandline;
+ bModeSetA = FALSE;
while (*ip)
{
- if (*ip == _T('%'))
+ if ( *ip == _T('%') )
{
- switch (*++ip)
+ UINT envNameLen;
+ LPCTSTR envVal = GetParsedEnvVar ( ip, &envNameLen, bModeSetA );
+ if ( envVal )
{
- case _T('%'):
- *cp++ = *ip++;
- break;
-
- case _T('0'):
- case _T('1'):
- case _T('2'):
- case _T('3'):
- case _T('4'):
- case _T('5'):
- case _T('6'):
- case _T('7'):
- case _T('8'):
- case _T('9'):
- if ((tp = FindArg (*ip - _T('0'))))
- {
- cp = _stpcpy (cp, tp);
- ip++;
- }
- else
- *cp++ = _T('%');
- break;
-
- case _T('?'):
- cp += _stprintf (cp, _T("%u"), nErrorLevel);
- ip++;
- break;
-
- default:
- tp = _tcschr(ip, _T('%'));
- if ((tp != NULL) &&
- (tp <= _tcschr(ip, _T(' ')) - 1))
- {
- TCHAR evar[512];
- *tp = _T('\0');
+ ip += envNameLen;
+ cp = _stpcpy ( cp, envVal );
+ }
+ }
- /* FIXME: This is just a quick hack!! */
- /* Do a proper memory allocation!! */
- if (GetEnvironmentVariable (ip, evar, 512))
- cp = _stpcpy (cp, evar);
+ if (_istcntrl (*ip))
+ *ip = _T(' ');
+ *cp++ = *ip++;
- ip = tp + 1;
+ /* HACK HACK HACK check whether bModeSetA needs to be toggled */
+ *cp = 0;
+ tmp = commandline;
+ tmp += _tcsspn(tmp,_T(" \t"));
+ /* first we find and skip and pre-redirections... */
+ while ( _tcschr(_T("<>"),*tmp)
+ || !_tcsncmp(tmp,_T("1>"),2)
+ || !_tcsncmp(tmp,_T("2>"),2) )
+ {
+ if ( _istdigit(*tmp) )
+ tmp += 2;
+ else
+ tmp++;
+ tmp += _tcsspn(tmp,_T(" \t"));
+ if ( *tmp == _T('\"') )
+ {
+ tmp = _tcschr(tmp+1,_T('\"'));
+ if ( tmp )
+ ++tmp;
+ }
+ else
+ tmp = _tcspbrk(tmp,_T(" \t"));
+ tmp += _tcsspn(tmp,_T(" \t"));
+ }
+ /* we should now be pointing to the actual command
+ * (if there is one yet)*/
+ if ( tmp )
+ {
+ /* if we're currently substituting ( which is default )
+ * check to see if we've parsed out a set/a. if so, we
+ * need to disable substitution until we come across a
+ * redirection */
+ if ( !bModeSetA )
+ {
+ /* look for set /a */
+ if ( !_tcsnicmp(tmp,_T("set"),3) )
+ {
+ tmp += 3;
+ tmp += _tcsspn(tmp,_T(" \t"));
+ if ( !_tcsnicmp(tmp,_T("/a"),2) )
+ bModeSetA = TRUE;
+ }
+ }
+ /* if we're not currently substituting, it means we're
+ * already inside a set /a. now we need to look for
+ * a redirection in order to turn redirection back on */
+ else
+ {
+ /* look for redirector of some kind after the command */
+ while ( (tmp = _tcspbrk ( tmp, _T("^<>|") )) )
+ {
+ if ( *tmp == _T('^') )
+ {
+ if ( _tcschr(_T("<>|&"), *++tmp ) && *tmp )
+ ++tmp;
}
else
{
- *cp++ = _T('%');
+ bModeSetA = FALSE;
+ break;
}
- break;
+ }
}
- continue;
}
-
- if (_istcntrl (*ip))
- *ip = _T(' ');
- *cp++ = *ip++;
}
*cp = _T('\0');
ConOutPuts (commandline);
}
- if (*commandline)
+ if (*commandline && !CheckCtrlBreak(BREAK_INPUT))
{
ParseCommandLine (commandline);
- if (bEcho && !bIgnoreEcho)
+ if (bEcho && !bIgnoreEcho && (!bIsBatch || bEchoThisLine))
ConOutChar ('\n');
bIgnoreEcho = FALSE;
}
*/
BOOL WINAPI BreakHandler (DWORD dwCtrlType)
{
-
+
+ DWORD dwWritten;
+ INPUT_RECORD rec;
+ static BOOL SelfGenerated = FALSE;
+
+ rec.EventType = KEY_EVENT;
+ rec.Event.KeyEvent.bKeyDown = TRUE;
+ rec.Event.KeyEvent.wRepeatCount = 1;
+ rec.Event.KeyEvent.wVirtualKeyCode = _T('C');
+ rec.Event.KeyEvent.wVirtualScanCode = _T('C') - 35;
+ rec.Event.KeyEvent.uChar.AsciiChar = _T('C');
+ rec.Event.KeyEvent.uChar.UnicodeChar = _T('C');
+ rec.Event.KeyEvent.dwControlKeyState = RIGHT_CTRL_PRESSED;
+
+ WriteConsoleInput(
+ hIn,
+ &rec,
+ 1,
+ &dwWritten);
+
if ((dwCtrlType != CTRL_C_EVENT) &&
(dwCtrlType != CTRL_BREAK_EVENT))
+ {
return FALSE;
-
+ }
+ else
+ {
+ if(SelfGenerated)
+ {
+ SelfGenerated = FALSE;
+ return TRUE;
+ }
+ }
+
if (bChildProcessRunning == TRUE)
{
- GenerateConsoleCtrlEvent (CTRL_C_EVENT,
- dwChildProcessId);
+ SelfGenerated = TRUE;
+ GenerateConsoleCtrlEvent (dwCtrlType, 0);
return TRUE;
}
+ bCtrlBreak = TRUE;
/* FIXME: Handle batch files */
- /* FIXME: Print "^C" */
+ //ConOutPrintf(_T("^C"));
return TRUE;
static VOID
ShowCommands (VOID)
{
- TCHAR szMsg[RC_STRING_MAX_SIZE];
-
/* print command list */
- LoadString(GetModuleHandle(NULL), STRING_CMD_HELP1, szMsg, RC_STRING_MAX_SIZE);
- ConOutPrintf(szMsg);
+ ConOutResPuts(STRING_CMD_HELP1);
PrintCommandList();
/* print feature list */
- LoadString(GetModuleHandle(NULL), STRING_CMD_HELP2, szMsg, RC_STRING_MAX_SIZE);
- ConOutPuts(szMsg);
+ ConOutResPuts(STRING_CMD_HELP2);
-#ifdef FEATURE_ALIASES
- LoadString(GetModuleHandle(NULL), STRING_CMD_HELP3, szMsg, RC_STRING_MAX_SIZE);
- ConOutPuts(szMsg);
+#ifdef FEATURE_ALIASES
+ ConOutResPuts(STRING_CMD_HELP3);
#endif
#ifdef FEATURE_HISTORY
- LoadString(GetModuleHandle(NULL), STRING_CMD_HELP4, szMsg, RC_STRING_MAX_SIZE);
- ConOutPuts(szMsg);
+ ConOutResPuts(STRING_CMD_HELP4);
#endif
#ifdef FEATURE_UNIX_FILENAME_COMPLETION
- LoadString(GetModuleHandle(NULL), STRING_CMD_HELP5, szMsg, RC_STRING_MAX_SIZE);
- ConOutPuts(szMsg);
+ ConOutResPuts(STRING_CMD_HELP5);
#endif
#ifdef FEATURE_DIRECTORY_STACK
- LoadString(GetModuleHandle(NULL), STRING_CMD_HELP6, szMsg, RC_STRING_MAX_SIZE);
- ConOutPuts(szMsg);
+ ConOutResPuts(STRING_CMD_HELP6);
#endif
#ifdef FEATURE_REDIRECTION
- LoadString(GetModuleHandle(NULL), STRING_CMD_HELP7, szMsg, RC_STRING_MAX_SIZE);
- ConOutPuts(szMsg);
+ ConOutResPuts(STRING_CMD_HELP7);
#endif
ConOutChar(_T('\n'));
}
static VOID
Initialize (int argc, TCHAR* argv[])
{
- TCHAR szMsg[RC_STRING_MAX_SIZE];
TCHAR commandline[CMDLINE_LENGTH];
TCHAR ModuleName[_MAX_PATH + 1];
INT i;
+ TCHAR lpBuffer[2];
//INT len;
//TCHAR *ptr, *cmdLine;
+ /* get version information */
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ GetVersionEx (&osvi);
-#ifdef _DEBUG
- INT x;
+ /* Some people like to run ReactOS cmd.exe on Win98, it helps in the
+ * build process. So don't link implicitly against ntdll.dll, load it
+ * dynamically instead */
+
+ if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ {
+ /* ntdll is always present on NT */
+ NtDllModule = GetModuleHandle(TEXT("ntdll.dll"));
+ }
+ else
+ {
+ /* not all 9x versions have a ntdll.dll, try to load it */
+ NtDllModule = LoadLibrary(TEXT("ntdll.dll"));
+ }
+ if (NtDllModule != NULL)
+ {
+ NtQueryInformationProcessPtr = (NtQueryInformationProcessProc)GetProcAddress(NtDllModule, "NtQueryInformationProcess");
+ NtReadVirtualMemoryPtr = (NtReadVirtualMemoryProc)GetProcAddress(NtDllModule, "NtReadVirtualMemory");
+ }
+
+
+#ifdef _DEBUG
DebugPrintf (_T("[command args:\n"));
- for (x = 0; x < argc; x++)
+ for (i = 0; i < argc; i++)
{
- DebugPrintf (_T("%d. %s\n"), x, argv[x]);
+ DebugPrintf (_T("%d. %s\n"), i, argv[i]);
}
DebugPrintf (_T("]\n"));
#endif
- /* get version information */
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- GetVersionEx (&osvi);
-
InitLocale ();
/* get default input and output console handles */
hOut = GetStdHandle (STD_OUTPUT_HANDLE);
hIn = GetStdHandle (STD_INPUT_HANDLE);
+ /* Set EnvironmentVariable PROMPT if it does not exists any env value.
+ for you can change the EnvirommentVariable for prompt before cmd start
+ this patch are not 100% right, if it does not exists a PROMPT value cmd should use
+ $P$G as defualt not set EnvirommentVariable PROMPT to $P$G if it does not exists */
+ if (GetEnvironmentVariable(_T("PROMPT"),lpBuffer, sizeof(lpBuffer) / sizeof(lpBuffer[0])) == 0)
+ SetEnvironmentVariable (_T("PROMPT"), _T("$P$G"));
+
if (argc >= 2 && !_tcsncmp (argv[1], _T("/?"), 2))
{
- LoadString(GetModuleHandle(NULL), STRING_CMD_HELP8, szMsg, RC_STRING_MAX_SIZE);
- ConOutPuts(szMsg);
+ ConOutResPaging(TRUE,STRING_CMD_HELP8);
ExitProcess(0);
}
SetConsoleMode (hIn, ENABLE_PROCESSED_INPUT);
++i;
if (i < argc)
{
- _tcscpy (commandline, argv[i]);
+ _tcscpy (commandline, _T("\""));
+ _tcscat (commandline, argv[i]);
+ _tcscat (commandline, _T("\""));
while (++i < argc)
{
_tcscat (commandline, _T(" "));
_tcscat (commandline, argv[i]);
}
-
ParseCommandLine(commandline);
}
}
{
ParseCommandLine (_T("\\cmdstart.bat"));
}
-#ifndef __REACTOS__
- else
- {
- /* try to run cmdstart.bat from install dir */
- LPTSTR p;
-
- _tcscpy (commandline, argv[0]);
- p = _tcsrchr (commandline, _T('\\')) + 1;
- _tcscpy (p, _T("cmdstart.bat"));
-
- if (IsExistingFile (_T("commandline")))
- {
- LoadString(GetModuleHandle(NULL), STRING_CMD_ERROR4, szMsg, RC_STRING_MAX_SIZE);
- ConErrPrintf(szMsg, commandline);
- ParseCommandLine (commandline);
- }
- }
-#endif
#ifdef FEATURE_DIR_STACK
/* initialize directory stack */
static VOID Cleanup (int argc, TCHAR *argv[])
{
- TCHAR szMsg[RC_STRING_MAX_SIZE];
-
/* run cmdexit.bat */
if (IsExistingFile (_T("cmdexit.bat")))
{
- LoadString(GetModuleHandle(NULL), STRING_CMD_ERROR5, szMsg, RC_STRING_MAX_SIZE);
- ConErrPrintf(szMsg);
+ ConErrResPuts(STRING_CMD_ERROR5);
ParseCommandLine (_T("cmdexit.bat"));
}
else if (IsExistingFile (_T("\\cmdexit.bat")))
{
- LoadString( GetModuleHandle(NULL), STRING_CMD_ERROR5, szMsg, RC_STRING_MAX_SIZE);
- ConErrPrintf ((LPTSTR)szMsg);
+ ConErrResPuts (STRING_CMD_ERROR5);
ParseCommandLine (_T("\\cmdexit.bat"));
}
-#ifndef __REACTOS__
- else
- {
- /* try to run cmdexit.bat from install dir */
- TCHAR commandline[CMDLINE_LENGTH];
- LPTSTR p;
-
- _tcscpy (commandline, argv[0]);
- p = _tcsrchr (commandline, _T('\\')) + 1;
- _tcscpy (p, _T("cmdexit.bat"));
-
- if (IsExistingFile (_T("commandline")))
- {
- LoadString(GetModuleHandle(NULL), STRING_CMD_ERROR4, szMsg, RC_STRING_MAX_SIZE);
- ConErrPrintf(szMsg, commandline);
- ParseCommandLine (commandline);
- }
- }
-#endif
#ifdef FEATURE_ALIASES
DestroyAlias ();
RemoveBreakHandler ();
SetConsoleMode( GetStdHandle( STD_INPUT_HANDLE ),
ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT );
-}
-#ifdef __REACTOS__
-#ifdef _UNICODE
-PWCHAR * _CommandLineToArgvW(PWCHAR lpCmdLine, int *pNumArgs)
-{
- PWCHAR * argvw = NULL;
- PWCHAR ptr = lpCmdLine;
- PWCHAR str;
- int len;
- int NumArgs;
-
- NumArgs = 0;
-
- while(lpCmdLine && *lpCmdLine)
- {
- while (iswspace(*lpCmdLine)) lpCmdLine++;
- if (*lpCmdLine)
- {
- if ((NumArgs % 10)==0)
- {
- PWCHAR * old_argvw = argvw;
- argvw = malloc((NumArgs + 10) * sizeof(PWCHAR));
- memcpy(argvw, old_argvw, NumArgs * sizeof(PWCHAR));
- free(old_argvw);
- }
- ptr = wcschr(lpCmdLine, L' ');
- if (ptr)
- {
- len = ptr - lpCmdLine;
- }
- else
- {
- len = wcslen(lpCmdLine);
- }
- str = malloc((len + 1) * sizeof(WCHAR));
- memcpy(str, lpCmdLine, len * sizeof(WCHAR));
- str[len] = 0;
- argvw[NumArgs]=str;
- NumArgs++;
- lpCmdLine = ptr;
- }
- }
- *pNumArgs = NumArgs;
- return argvw;
+ if (NtDllModule != NULL)
+ {
+ FreeLibrary(NtDllModule);
+ }
}
-#endif
-#endif
/*
* main function
*/
#ifdef _UNICODE
-int main(void)
+int _main(void)
#else
-int main (int argc, char *argv[])
+int _main (int argc, char *argv[])
#endif
{
- CONSOLE_SCREEN_BUFFER_INFO Info;
- INT nExitCode;
+ TCHAR startPath[MAX_PATH];
+ CONSOLE_SCREEN_BUFFER_INFO Info;
+ INT nExitCode;
#ifdef _UNICODE
- PWCHAR * argv;
- int argc=0;
-#ifdef __REACTOS__
- argv = _CommandLineToArgvW(GetCommandLineW(), &argc);
-#else
- argv = CommandLineToArgvW(GetCommandLineW(), &argc);
-#endif
+ PWCHAR * argv;
+ int argc=0;
+ argv = CommandLineToArgvW(GetCommandLineW(), &argc);
#endif
- SetFileApisToOEM();
+ GetCurrentDirectory(MAX_PATH,startPath);
+ _tchdir(startPath);
+
+ SetFileApisToOEM();
+ InputCodePage= 0;
+ OutputCodePage = 0;
+
+ hConsole = CreateFile(_T("CONOUT$"), GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, 0, NULL);
+ if (GetConsoleScreenBufferInfo(hConsole, &Info) == FALSE)
+ {
+ ConErrFormatMessage(GetLastError());
+ return(1);
+ }
+ wColor = Info.wAttributes;
+ wDefColor = wColor;
- hConsole = CreateFile(_T("CONOUT$"), GENERIC_READ|GENERIC_WRITE,
- FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
- OPEN_EXISTING, 0, NULL);
- if (GetConsoleScreenBufferInfo(hConsole, &Info) == FALSE)
- {
- ConOutFormatMessage(GetLastError());
- return(1);
- }
- wColor = Info.wAttributes;
- wDefColor = wColor;
+ InputCodePage= GetConsoleCP();
+ OutputCodePage = GetConsoleOutputCP();
+ CMD_ModuleHandle = GetModuleHandle(NULL);
- /* check switches on command-line */
- Initialize(argc, argv);
+ /* check switches on command-line */
+ Initialize(argc, argv);
- /* call prompt routine */
- nExitCode = ProcessInput(FALSE);
+ /* call prompt routine */
+ nExitCode = ProcessInput(FALSE);
- /* do the cleanup */
- Cleanup(argc, argv);
+ /* do the cleanup */
+ Cleanup(argc, argv);
- return(nExitCode);
+ return(nExitCode);
}
/* EOF */