mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
[CMD]: Diverse improvements:
- Add pre-support for "enable extensions". - Load CMD settings at startup from the registry (from HKLM and HKCU Software\\Microsoft\\Command Processor reg key), as done by Windows' CMD.EXE. - Add support for CMD.EXE /E(:OFF), /X, /Y command-line switches. - Correctly set the console colors when using CMD.EXE /T: switch. - Start support for two control characters for the completion: the standard CompletionChar and the PathCompletionChar (if one desires to autocomplete *just* directory names -- or associated -- but not everything), as Windows' CMD.EXE offers. svn path=/trunk/; revision=75997
This commit is contained in:
parent
7d6b5d99a6
commit
cd45987d1a
4 changed files with 256 additions and 41 deletions
|
@ -162,6 +162,7 @@ INT nErrorLevel = 0; /* Errorlevel of last launched external program */
|
|||
CRITICAL_SECTION ChildProcessRunningLock;
|
||||
BOOL bUnicodeOutput = FALSE;
|
||||
BOOL bDisableBatchEcho = FALSE;
|
||||
BOOL bEnableExtensions = TRUE;
|
||||
BOOL bDelayedExpansion = FALSE;
|
||||
BOOL bTitleSet = FALSE;
|
||||
DWORD dwChildProcessId = 0;
|
||||
|
@ -174,7 +175,7 @@ static NtQueryInformationProcessProc NtQueryInformationProcessPtr = NULL;
|
|||
static NtReadVirtualMemoryProc NtReadVirtualMemoryPtr = NULL;
|
||||
|
||||
#ifdef INCLUDE_CMD_COLOR
|
||||
WORD wDefColor; /* default color */
|
||||
WORD wDefColor = 0; /* Default color */
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -1532,14 +1533,164 @@ ShowCommands (VOID)
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
static VOID
|
||||
ExecuteAutoRunFile(HKEY hkeyRoot)
|
||||
LoadRegistrySettings(HKEY hKeyRoot)
|
||||
{
|
||||
LONG lRet;
|
||||
HKEY hKey;
|
||||
/*
|
||||
* Buffer big enough to hold the string L"4294967295",
|
||||
* corresponding to the literal 0xFFFFFFFF (MAX_ULONG) in decimal.
|
||||
*/
|
||||
DWORD Buffer[6];
|
||||
DWORD dwType, len;
|
||||
|
||||
lRet = RegOpenKeyEx(hKeyRoot,
|
||||
_T("Software\\Microsoft\\Command Processor"),
|
||||
0,
|
||||
KEY_QUERY_VALUE,
|
||||
&hKey);
|
||||
if (lRet != ERROR_SUCCESS)
|
||||
return;
|
||||
|
||||
#ifdef INCLUDE_CMD_COLOR
|
||||
len = sizeof(Buffer);
|
||||
lRet = RegQueryValueEx(hKey,
|
||||
_T("DefaultColor"),
|
||||
NULL,
|
||||
&dwType,
|
||||
(LPBYTE)&Buffer,
|
||||
&len);
|
||||
if (lRet == ERROR_SUCCESS)
|
||||
{
|
||||
/* Overwrite the default attributes */
|
||||
if (dwType == REG_DWORD)
|
||||
wDefColor = (WORD)*(PDWORD)Buffer;
|
||||
else if (dwType == REG_SZ)
|
||||
wDefColor = (WORD)_tcstol((PTSTR)Buffer, NULL, 0);
|
||||
}
|
||||
// else, use the default attributes retrieved before.
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
len = sizeof(Buffer);
|
||||
lRet = RegQueryValueEx(hKey,
|
||||
_T("DisableUNCCheck"),
|
||||
NULL,
|
||||
&dwType,
|
||||
(LPBYTE)&Buffer,
|
||||
&len);
|
||||
if (lRet == ERROR_SUCCESS)
|
||||
{
|
||||
/* Overwrite the default setting */
|
||||
if (dwType == REG_DWORD)
|
||||
bDisableUNCCheck = !!*(PDWORD)Buffer;
|
||||
else if (dwType == REG_SZ)
|
||||
bDisableUNCCheck = (_ttol((PTSTR)Buffer) == 1);
|
||||
}
|
||||
// else, use the default setting set globally.
|
||||
#endif
|
||||
|
||||
len = sizeof(Buffer);
|
||||
lRet = RegQueryValueEx(hKey,
|
||||
_T("DelayedExpansion"),
|
||||
NULL,
|
||||
&dwType,
|
||||
(LPBYTE)&Buffer,
|
||||
&len);
|
||||
if (lRet == ERROR_SUCCESS)
|
||||
{
|
||||
/* Overwrite the default setting */
|
||||
if (dwType == REG_DWORD)
|
||||
bDelayedExpansion = !!*(PDWORD)Buffer;
|
||||
else if (dwType == REG_SZ)
|
||||
bDelayedExpansion = (_ttol((PTSTR)Buffer) == 1);
|
||||
}
|
||||
// else, use the default setting set globally.
|
||||
|
||||
len = sizeof(Buffer);
|
||||
lRet = RegQueryValueEx(hKey,
|
||||
_T("EnableExtensions"),
|
||||
NULL,
|
||||
&dwType,
|
||||
(LPBYTE)&Buffer,
|
||||
&len);
|
||||
if (lRet == ERROR_SUCCESS)
|
||||
{
|
||||
/* Overwrite the default setting */
|
||||
if (dwType == REG_DWORD)
|
||||
bEnableExtensions = !!*(PDWORD)Buffer;
|
||||
else if (dwType == REG_SZ)
|
||||
bEnableExtensions = (_ttol((PTSTR)Buffer) == 1);
|
||||
}
|
||||
// else, use the default setting set globally.
|
||||
|
||||
len = sizeof(Buffer);
|
||||
lRet = RegQueryValueEx(hKey,
|
||||
_T("CompletionChar"),
|
||||
NULL,
|
||||
&dwType,
|
||||
(LPBYTE)&Buffer,
|
||||
&len);
|
||||
if (lRet == ERROR_SUCCESS)
|
||||
{
|
||||
/* Overwrite the default setting */
|
||||
if (dwType == REG_DWORD)
|
||||
AutoCompletionChar = (TCHAR)*(PDWORD)Buffer;
|
||||
else if (dwType == REG_SZ)
|
||||
AutoCompletionChar = (TCHAR)_tcstol((PTSTR)Buffer, NULL, 0);
|
||||
}
|
||||
// else, use the default setting set globally.
|
||||
|
||||
/* Validity check */
|
||||
if (IS_COMPLETION_DISABLED(AutoCompletionChar))
|
||||
{
|
||||
/* Disable autocompletion */
|
||||
AutoCompletionChar = 0x20;
|
||||
}
|
||||
|
||||
len = sizeof(Buffer);
|
||||
lRet = RegQueryValueEx(hKey,
|
||||
_T("PathCompletionChar"),
|
||||
NULL,
|
||||
&dwType,
|
||||
(LPBYTE)&Buffer,
|
||||
&len);
|
||||
if (lRet == ERROR_SUCCESS)
|
||||
{
|
||||
/* Overwrite the default setting */
|
||||
if (dwType == REG_DWORD)
|
||||
PathCompletionChar = (TCHAR)*(PDWORD)Buffer;
|
||||
else if (dwType == REG_SZ)
|
||||
PathCompletionChar = (TCHAR)_tcstol((PTSTR)Buffer, NULL, 0);
|
||||
}
|
||||
// else, use the default setting set globally.
|
||||
|
||||
/* Validity check */
|
||||
if (IS_COMPLETION_DISABLED(PathCompletionChar))
|
||||
{
|
||||
/* Disable autocompletion */
|
||||
PathCompletionChar = 0x20;
|
||||
}
|
||||
|
||||
/* Adjust completion chars */
|
||||
if (PathCompletionChar >= 0x20 && AutoCompletionChar < 0x20)
|
||||
PathCompletionChar = AutoCompletionChar;
|
||||
else if (AutoCompletionChar >= 0x20 && PathCompletionChar < 0x20)
|
||||
AutoCompletionChar = PathCompletionChar;
|
||||
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
|
||||
static VOID
|
||||
ExecuteAutoRunFile(HKEY hKeyRoot)
|
||||
{
|
||||
TCHAR autorun[2048];
|
||||
DWORD len = sizeof autorun;
|
||||
HKEY hkey;
|
||||
|
||||
if (RegOpenKeyEx(hkeyRoot,
|
||||
if (RegOpenKeyEx(hKeyRoot,
|
||||
_T("SOFTWARE\\Microsoft\\Command Processor"),
|
||||
0,
|
||||
KEY_READ,
|
||||
|
@ -1612,18 +1763,45 @@ GetCmdLineCommand(TCHAR *commandline, TCHAR *ptr, BOOL AlwaysStrip)
|
|||
_tcscpy(commandline, ptr);
|
||||
}
|
||||
|
||||
|
||||
#ifdef INCLUDE_CMD_COLOR
|
||||
|
||||
BOOL ConGetDefaultAttributes(PWORD pwDefAttr)
|
||||
{
|
||||
BOOL Success;
|
||||
HANDLE hConsole;
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
|
||||
/* Do not modify *pwDefAttr if we fail, in which case use default attributes */
|
||||
|
||||
hConsole = CreateFile(_T("CONOUT$"), GENERIC_READ|GENERIC_WRITE,
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
|
||||
OPEN_EXISTING, 0, NULL);
|
||||
if (hConsole == INVALID_HANDLE_VALUE)
|
||||
return FALSE; // No default console
|
||||
|
||||
Success = GetConsoleScreenBufferInfo(hConsole, &csbi);
|
||||
if (Success)
|
||||
*pwDefAttr = csbi.wAttributes;
|
||||
|
||||
CloseHandle(hConsole);
|
||||
return Success;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* set up global initializations and process parameters
|
||||
* Set up global initializations and process parameters
|
||||
*/
|
||||
static VOID
|
||||
Initialize()
|
||||
Initialize(VOID)
|
||||
{
|
||||
HMODULE NtDllModule;
|
||||
TCHAR commandline[CMDLINE_LENGTH];
|
||||
TCHAR ModuleName[_MAX_PATH + 1];
|
||||
INT nExitCode;
|
||||
|
||||
//INT len;
|
||||
TCHAR *ptr, *cmdLine, option = 0;
|
||||
BOOL AlwaysStrip = FALSE;
|
||||
BOOL AutoRun = TRUE;
|
||||
|
@ -1641,9 +1819,14 @@ Initialize()
|
|||
NtReadVirtualMemoryPtr = (NtReadVirtualMemoryProc)GetProcAddress(NtDllModule, "NtReadVirtualMemory");
|
||||
}
|
||||
|
||||
/* Load the registry settings */
|
||||
LoadRegistrySettings(HKEY_LOCAL_MACHINE);
|
||||
LoadRegistrySettings(HKEY_CURRENT_USER);
|
||||
|
||||
/* Initialize our locale */
|
||||
InitLocale();
|
||||
|
||||
/* get default input and output console handles */
|
||||
/* Get default input and output console handles */
|
||||
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
hIn = GetStdHandle(STD_INPUT_HANDLE);
|
||||
|
||||
|
@ -1651,17 +1834,17 @@ Initialize()
|
|||
InitPrompt();
|
||||
|
||||
#ifdef FEATURE_DIR_STACK
|
||||
/* initialize directory stack */
|
||||
/* Initialize directory stack */
|
||||
InitDirectoryStack();
|
||||
#endif
|
||||
|
||||
#ifdef FEATURE_HISTORY
|
||||
/*initialize history*/
|
||||
/* Initialize history */
|
||||
InitHistory();
|
||||
#endif
|
||||
|
||||
/* Set COMSPEC environment variable */
|
||||
if (0 != GetModuleFileName (NULL, ModuleName, _MAX_PATH + 1))
|
||||
if (GetModuleFileName(NULL, ModuleName, ARRAYSIZE(ModuleName)) != 0)
|
||||
{
|
||||
ModuleName[_MAX_PATH] = _T('\0');
|
||||
SetEnvironmentVariable (_T("COMSPEC"), ModuleName);
|
||||
|
@ -1731,9 +1914,8 @@ Initialize()
|
|||
#ifdef INCLUDE_CMD_COLOR
|
||||
else if (!_tcsnicmp(ptr, _T("/T:"), 3))
|
||||
{
|
||||
/* process /T (color) argument */
|
||||
/* Process /T (color) argument; overwrite any previous settings */
|
||||
wDefColor = (WORD)_tcstoul(&ptr[3], &ptr, 16);
|
||||
SetScreenColor(wDefColor, FALSE);
|
||||
}
|
||||
#endif
|
||||
else if (option == _T('U'))
|
||||
|
@ -1742,11 +1924,41 @@ Initialize()
|
|||
}
|
||||
else if (option == _T('V'))
|
||||
{
|
||||
// FIXME: Check validity of the parameter given to V !
|
||||
bDelayedExpansion = _tcsnicmp(&ptr[2], _T(":OFF"), 4);
|
||||
}
|
||||
else if (option == _T('E'))
|
||||
{
|
||||
// FIXME: Check validity of the parameter given to E !
|
||||
bEnableExtensions = _tcsnicmp(&ptr[2], _T(":OFF"), 4);
|
||||
}
|
||||
else if (option == _T('X'))
|
||||
{
|
||||
/* '/X' is identical to '/E:ON' */
|
||||
bEnableExtensions = TRUE;
|
||||
}
|
||||
else if (option == _T('Y'))
|
||||
{
|
||||
/* '/Y' is identical to '/E:OFF' */
|
||||
bEnableExtensions = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef INCLUDE_CMD_COLOR
|
||||
if (wDefColor == 0)
|
||||
{
|
||||
/*
|
||||
* If we still do not have the console colour attribute set,
|
||||
* retrieve the default one.
|
||||
*/
|
||||
ConGetDefaultAttributes(&wDefColor);
|
||||
}
|
||||
|
||||
if (wDefColor != 0)
|
||||
SetScreenColor(wDefColor, FALSE);
|
||||
#endif
|
||||
|
||||
if (!*ptr)
|
||||
{
|
||||
/* If neither /C or /K was given, display a simple version string */
|
||||
|
@ -1779,7 +1991,7 @@ Initialize()
|
|||
}
|
||||
|
||||
|
||||
static VOID Cleanup()
|
||||
static VOID Cleanup(VOID)
|
||||
{
|
||||
/* run cmdexit.bat */
|
||||
if (IsExistingFile (_T("cmdexit.bat")))
|
||||
|
@ -1823,52 +2035,33 @@ static VOID Cleanup()
|
|||
*/
|
||||
int _tmain(int argc, const TCHAR *argv[])
|
||||
{
|
||||
HANDLE hConsole;
|
||||
TCHAR startPath[MAX_PATH];
|
||||
CONSOLE_SCREEN_BUFFER_INFO Info;
|
||||
|
||||
InitializeCriticalSection(&ChildProcessRunningLock);
|
||||
lpOriginalEnvironment = DuplicateEnvironment();
|
||||
|
||||
GetCurrentDirectory(MAX_PATH,startPath);
|
||||
GetCurrentDirectory(ARRAYSIZE(startPath), 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 (hConsole != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (!GetConsoleScreenBufferInfo(hConsole, &Info))
|
||||
{
|
||||
ConErrFormatMessage(GetLastError());
|
||||
CloseHandle(hConsole);
|
||||
return(1);
|
||||
}
|
||||
wDefColor = Info.wAttributes;
|
||||
CloseHandle(hConsole);
|
||||
}
|
||||
|
||||
InputCodePage = GetConsoleCP();
|
||||
OutputCodePage = GetConsoleOutputCP();
|
||||
|
||||
CMD_ModuleHandle = GetModuleHandle(NULL);
|
||||
|
||||
/* check switches on command-line */
|
||||
/* Perform general initialization, parse switches on command-line */
|
||||
Initialize();
|
||||
|
||||
/* call prompt routine */
|
||||
/* Call prompt routine */
|
||||
ProcessInput();
|
||||
|
||||
/* do the cleanup */
|
||||
/* Do the cleanup */
|
||||
Cleanup();
|
||||
|
||||
cmd_free(lpOriginalEnvironment);
|
||||
|
||||
cmd_exit(nErrorLevel);
|
||||
return(nErrorLevel);
|
||||
return nErrorLevel;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
/* 16k = max buffer size */
|
||||
#define BUFF_SIZE 16384
|
||||
|
||||
/* global variables */
|
||||
/* Global variables */
|
||||
extern HANDLE hOut;
|
||||
extern HANDLE hIn;
|
||||
extern LPTSTR lpOriginalEnvironment;
|
||||
|
@ -61,6 +61,7 @@ extern BOOL bCtrlBreak;
|
|||
extern BOOL bIgnoreEcho;
|
||||
extern BOOL bExit;
|
||||
extern BOOL bDisableBatchEcho;
|
||||
extern BOOL bEnableExtensions;
|
||||
extern BOOL bDelayedExpansion;
|
||||
extern INT nErrorLevel;
|
||||
extern SHORT maxx;
|
||||
|
@ -116,6 +117,12 @@ extern HANDLE CMD_ModuleHandle;
|
|||
/* Prototypes for CMDINPUT.C */
|
||||
BOOL ReadCommand (LPTSTR, INT);
|
||||
|
||||
extern TCHAR AutoCompletionChar;
|
||||
extern TCHAR PathCompletionChar;
|
||||
|
||||
#define IS_COMPLETION_DISABLED(CompletionCtrl) \
|
||||
((CompletionCtrl) == 0x00 || (CompletionCtrl) == 0x0D || (CompletionCtrl) >= 0x20)
|
||||
|
||||
|
||||
/* Prototypes for CMDTABLE.C */
|
||||
#define CMD_SPECIAL 1
|
||||
|
|
|
@ -102,6 +102,16 @@
|
|||
|
||||
#include "precomp.h"
|
||||
|
||||
/*
|
||||
* See https://technet.microsoft.com/en-us/library/cc978715.aspx
|
||||
* and https://technet.microsoft.com/en-us/library/cc940805.aspx
|
||||
* to know the differences between those two settings.
|
||||
* Values 0x00, 0x0D (carriage return) and 0x20 (space) disable completion.
|
||||
*/
|
||||
TCHAR AutoCompletionChar = _T('\t'); // Default is 0x20
|
||||
TCHAR PathCompletionChar = _T('\t'); // Default is 0x20
|
||||
|
||||
|
||||
SHORT maxx;
|
||||
SHORT maxy;
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
typedef struct _SETLOCAL
|
||||
{
|
||||
struct _SETLOCAL *Prev;
|
||||
BOOL EnableExtensions;
|
||||
BOOL DelayedExpansion;
|
||||
LPTSTR Environment;
|
||||
} SETLOCAL;
|
||||
|
@ -52,6 +53,7 @@ INT cmd_setlocal(LPTSTR param)
|
|||
return 1;
|
||||
}
|
||||
Saved->Prev = bc->setlocal;
|
||||
Saved->EnableExtensions = bEnableExtensions;
|
||||
Saved->DelayedExpansion = bDelayedExpansion;
|
||||
Saved->Environment = DuplicateEnvironment();
|
||||
if (!Saved->Environment)
|
||||
|
@ -68,9 +70,11 @@ INT cmd_setlocal(LPTSTR param)
|
|||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
if (!_tcsicmp(arg[i], _T("enableextensions")))
|
||||
/* not implemented, ignore */;
|
||||
/* FIXME: not implemented! */
|
||||
bEnableExtensions = TRUE;
|
||||
else if (!_tcsicmp(arg[i], _T("disableextensions")))
|
||||
/* not implemented, ignore */;
|
||||
/* FIXME: not implemented! */
|
||||
bEnableExtensions = FALSE;
|
||||
else if (!_tcsicmp(arg[i], _T("enabledelayedexpansion")))
|
||||
bDelayedExpansion = TRUE;
|
||||
else if (!_tcsicmp(arg[i], _T("disabledelayedexpansion")))
|
||||
|
@ -97,6 +101,7 @@ INT cmd_endlocal(LPTSTR param)
|
|||
return 0;
|
||||
bc->setlocal = Saved->Prev;
|
||||
|
||||
bEnableExtensions = Saved->EnableExtensions;
|
||||
bDelayedExpansion = Saved->DelayedExpansion;
|
||||
|
||||
/* First, clear out the environment. Since making any changes to the
|
||||
|
|
Loading…
Reference in a new issue