⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cmd.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 3 页
字号:
		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(bc == NULL)
        {
            //
            // No batch file to see here, move along
            //
            if ( !GrowIfNecessary ( 3, &ret, &retlen ) )
                return NULL;
            ret[0] = _T('%');
            ret[1] = _T('*');
            ret[2] = 0;
            if ( varNameLen )
                *varNameLen = 2;
            return ret;
        }

        //
        // Copy over the raw params(not including the batch file name
        //
        if ( !GrowIfNecessary ( _tcslen(bc->raw_params)+1, &ret, &retlen ) )
            return NULL;
        if ( varNameLen )
            *varNameLen = 2;
        _tcscpy ( ret, bc->raw_params );
        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
 *
 */

static INT
ProcessInput (BOOL bFlag)
{
	TCHAR commandline[CMDLINE_LENGTH];
	TCHAR readline[CMDLINE_LENGTH];
	LPTSTR ip;
	LPTSTR cp;
	LPCTSTR tmp;
	BOOL bEchoThisLine;
	BOOL bModeSetA;
        BOOL bIsBatch;

	do
	{
		/* if no batch input then... */
		if (!(ip = ReadBatchLine (&bEchoThisLine)))
		{
			if (bFlag)
				return nErrorLevel;

			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('%') )
			{
				UINT envNameLen;
				LPCTSTR envVal = GetParsedEnvVar ( ip, &envNameLen, bModeSetA );
				if ( envVal )
				{
					ip += envNameLen;
					cp = _stpcpy ( cp, envVal );
				}
			}

			if (_istcntrl (*ip))
				*ip = _T(' ');
			*cp++ = *ip++;

			/* 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 (( tmp ) &&
				( _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"));
				if ( tmp )
					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
						{
							bModeSetA = FALSE;
							break;
						}
					}
				}
			}
		}

		*cp = _T('\0');

		/* strip trailing spaces */
		while ((--cp >= commandline) && _istspace (*cp));

		*(cp + 1) = _T('\0');

		/* JPP 19980807 */
		/* Echo batch file line */
		if (bEchoThisLine)
		{
			PrintPrompt ();
			ConOutPuts (commandline);
		}

		if (!CheckCtrlBreak(BREAK_INPUT) && *commandline)
		{
			ParseCommandLine (commandline);
			if (bEcho && !bIgnoreEcho && (!bIsBatch || bEchoThisLine))
				ConOutChar ('\n');
			bIgnoreEcho = FALSE;
		}
	}
	while (!bCanExit || !bExit);

	return nErrorLevel;
}


/*
 * control-break handler.
 */
BOOL WINAPI BreakHandler (DWORD dwCtrlType)
{

	DWORD			dwWritten;
	INPUT_RECORD	rec;
	static BOOL SelfGenerated = FALSE;
    
 	if ((dwCtrlType != CTRL_C_EVENT) &&
	    (dwCtrlType != CTRL_BREAK_EVENT))
	{
		return FALSE;
	}
	else
	{		
		if(SelfGenerated)
		{
			SelfGenerated = FALSE;
			return TRUE;
		}
	}
	
	if (bChildProcessRunning == TRUE)
	{
		SelfGenerated = TRUE;
		GenerateConsoleCtrlEvent (dwCtrlType, 0);
		return TRUE;
	}

    
    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);
        
	bCtrlBreak = TRUE;
	/* FIXME: Handle batch files */

	//ConOutPrintf(_T("^C"));


	return TRUE;
}


VOID AddBreakHandler (VOID)
{
	SetConsoleCtrlHandler ((PHANDLER_ROUTINE)BreakHandler, TRUE);
}


VOID RemoveBreakHandler (VOID)
{
	SetConsoleCtrlHandler ((PHANDLER_ROUTINE)BreakHandler, FALSE);
}


/*
 * show commands and options that are available.
 *
 */
#if 0
static VOID
ShowCommands (VOID)
{
	/* print command list */
	ConOutResPuts(STRING_CMD_HELP1);
	PrintCommandList();

	/* print feature list */
	ConOutResPuts(STRING_CMD_HELP2);

#ifdef FEATURE_ALIASES
	ConOutResPuts(STRING_CMD_HELP3);
#endif
#ifdef FEATURE_HISTORY
	ConOutResPuts(STRING_CMD_HELP4);
#endif
#ifdef FEATURE_UNIX_FILENAME_COMPLETION
	ConOutResPuts(STRING_CMD_HELP5);
#endif
#ifdef FEATURE_DIRECTORY_STACK
	ConOutResPuts(STRING_CMD_HELP6);
#endif
#ifdef FEATURE_REDIRECTION
	ConOutResPuts(STRING_CMD_HELP7);
#endif
	ConOutChar(_T('\n'));
}
#endif

/*
 * set up global initializations and process parameters
 *
 * argc - number of parameters to command.com
 * argv - command-line parameters
 *
 */
static VOID
Initialize (int argc, const TCHAR* argv[])
{
	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);

	/* 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 (i = 0; i < argc; i++)
	{
		DebugPrintf (_T("%d. %s\n"), i, argv[i]);
	}
	DebugPrintf (_T("]\n"));
#endif

	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))
	{
		ConOutResPaging(TRUE,STRING_CMD_HELP8);
		cmd_exit(0);
	}
	SetConsoleMode (hIn, ENABLE_PROCESSED_INPUT);

#ifdef INCLUDE_CMD_CHDIR
	InitLastPath ();
#endif

#ifdef FATURE_ALIASES
	InitializeAlias ();
#endif

	if (argc >= 2)
	{
		for (i = 1; i < argc; i++)
		{
			if (!_tcsicmp (argv[i], _T("/p")))
			{
				if (!IsExistingFile (_T("\\autoexec.bat")))
				{
#ifdef INCLUDE_CMD_DATE
					cmd_date (_T(""), _T(""));
#endif
#ifdef INCLUDE_CMD_TIME
					cmd_time (_T(""), _T(""));
#endif
				}
				else
				{
					ParseCommandLine (_T("\\autoexec.bat"));
				}
				bCanExit = FALSE;
			}
			else if (!_tcsicmp (argv[i], _T("/c")))
			{
				/* This just runs a program and exits */
				++i;
				if (i < argc)
				{
					_tcscpy (commandline, argv[i]);
					while (++i < argc)
					{
						_tcscat (commandline, _T(" "));
						_tcscat (commandline, argv[i]);
					}

					ParseCommandLine(commandline);
					cmd_exit (ProcessInput (TRUE));
				}
				else
				{
					cmd_exit (0);
				}
			}
			else if (!_tcsicmp (argv[i], _T("/k")))
			{
				/* This just runs a program and remains */
				++i;
				if (i < argc)
				{
					_tcscpy (commandline, _T("\""));
					_tcscat (commandline, argv[i]);
					_tcscat (commandline, _T("\""));
					while (++i < argc)
					{
						_tcscat (commandline, _T(" "));
						_tcscat (commandline, argv[i]);
					}
					ParseCommandLine(commandline);
				}
			}
#ifdef INCLUDE_CMD_COLOR
			else if (!_tcsnicmp (argv[i], _T("/t:"), 3))
			{
				/* process /t (color) argument */
				wDefColor = (WORD)_tcstoul (&argv[i][3], NULL, 16);
				wColor = wDefColor;
				SetScreenColor (wColor, TRUE);
			}
#endif
		}
	}

	/* run cmdstart.bat */
	if (IsExistingFile (_T("cmdstart.bat")))
	{
		ParseCommandLine (_T("cmdstart.bat"));
	}
	else if (IsExistingFile (_T("\\cmdstart.bat")))
	{
		ParseCommandLine (_T("\\cmdstart.bat"));
	}

#ifdef FEATURE_DIR_STACK
	/* initialize directory stack */
	InitDirectoryStack ();
#endif


#ifdef FEATURE_HISTORY
	/*initialize history*/
	InitHistory();
#endif

	/* Set COMSPEC environment variable */
	if (0 != GetModuleFileName (NULL, ModuleName, _MAX_PATH + 1))
	{
		ModuleName[_MAX_PATH] = _T('\0');
		SetEnvironmentVariable (_T("COMSPEC"), ModuleName);
	}

	/* add ctrl break handler */
	AddBreakHandler ();
}


static VOID Cleanup (int argc, const TCHAR *argv[])
{
	/* run cmdexit.bat */
	if (IsExistingFile (_T("cmdexit.bat")))
	{
		ConErrResPuts(STRING_CMD_ERROR5);

		ParseCommandLine (_T("cmdexit.bat"));
	}
	else if (IsExistingFile (_T("\\cmdexit.bat")))
	{
		ConErrResPuts (STRING_CMD_ERROR5);
		ParseCommandLine (_T("\\cmdexit.bat"));
	}

#ifdef FEATURE_ALIASES
	DestroyAlias ();
#endif

#ifdef FEATURE_DIECTORY_STACK
	/* destroy directory stack */
	DestroyDirectoryStack ();
#endif

#ifdef INCLUDE_CMD_CHDIR
	FreeLastPath ();
#endif

#ifdef FEATURE_HISTORY
	CleanHistory();
#endif


	/* remove ctrl break handler */
	RemoveBreakHandler ();
	SetConsoleMode( GetStdHandle( STD_INPUT_HANDLE ),
			ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT );

	if (NtDllModule != NULL)
	{
		FreeLibrary(NtDllModule);
	}
}

/*
 * main function
 */
int cmd_main (int argc, const TCHAR *argv[])
{
	TCHAR startPath[MAX_PATH];
	CONSOLE_SCREEN_BUFFER_INFO Info;
	INT nExitCode;

	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;

	InputCodePage= GetConsoleCP();
	OutputCodePage = GetConsoleOutputCP();
	CMD_ModuleHandle = GetModuleHandle(NULL);

	/* check switches on command-line */
	Initialize(argc, argv);

	/* call prompt routine */
	nExitCode = ProcessInput(FALSE);

	/* do the cleanup */
	Cleanup(argc, argv);

	cmd_exit(nExitCode);
	return(nExitCode);
}

/* EOF */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -