Author: hbelusca
Date: Sat Sep 30 11:39:08 2017
New Revision: 75997
URL: 
http://svn.reactos.org/svn/reactos?rev=75997&view=rev
Log:
[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.
Modified:
    trunk/reactos/base/shell/cmd/cmd.c
    trunk/reactos/base/shell/cmd/cmd.h
    trunk/reactos/base/shell/cmd/cmdinput.c
    trunk/reactos/base/shell/cmd/setlocal.c
Modified: trunk/reactos/base/shell/cmd/cmd.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/cmd.c?rev=7…
==============================================================================
--- trunk/reactos/base/shell/cmd/cmd.c  [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/cmd.c  [iso-8859-1] Sat Sep 30 11:39:08 2017
@@ -162,6 +162,7 @@
 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 NtReadVirtualMemoryProc       NtReadVirtualMemoryPtr = NULL;
 #ifdef INCLUDE_CMD_COLOR
-WORD wDefColor;           /* default color */
+WORD wDefColor = 0;     /* Default color */
 #endif
 /*
@@ -1532,14 +1533,164 @@
 }
 #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 @@
     _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 @@
         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 @@
     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 @@
 #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,10 +1924,40 @@
             }
             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)
     {
@@ -1779,7 +1991,7 @@
 }
-static VOID Cleanup()
+static VOID Cleanup(VOID)
 {
     /* run cmdexit.bat */
     if (IsExistingFile (_T("cmdexit.bat")))
@@ -1823,52 +2035,33 @@
  */
 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 */
Modified: trunk/reactos/base/shell/cmd/cmd.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/cmd.h?rev=7…
==============================================================================
--- trunk/reactos/base/shell/cmd/cmd.h  [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/cmd.h  [iso-8859-1] Sat Sep 30 11:39:08 2017
@@ -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   bIgnoreEcho;
 extern BOOL   bExit;
 extern BOOL   bDisableBatchEcho;
+extern BOOL   bEnableExtensions;
 extern BOOL   bDelayedExpansion;
 extern INT    nErrorLevel;
 extern SHORT  maxx;
@@ -115,6 +116,12 @@
 /* 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 */
Modified: trunk/reactos/base/shell/cmd/cmdinput.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/cmdinput.c?…
==============================================================================
--- trunk/reactos/base/shell/cmd/cmdinput.c     [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/cmdinput.c     [iso-8859-1] Sat Sep 30 11:39:08 2017
@@ -101,6 +101,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;
Modified: trunk/reactos/base/shell/cmd/setlocal.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/setlocal.c?…
==============================================================================
--- trunk/reactos/base/shell/cmd/setlocal.c     [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/setlocal.c     [iso-8859-1] Sat Sep 30 11:39:08 2017
@@ -12,6 +12,7 @@
 typedef struct _SETLOCAL
 {
     struct _SETLOCAL *Prev;
+    BOOL EnableExtensions;
     BOOL DelayedExpansion;
     LPTSTR Environment;
 } SETLOCAL;
@@ -52,6 +53,7 @@
         return 1;
     }
     Saved->Prev = bc->setlocal;
+    Saved->EnableExtensions = bEnableExtensions;
     Saved->DelayedExpansion = bDelayedExpansion;
     Saved->Environment = DuplicateEnvironment();
     if (!Saved->Environment)
@@ -68,9 +70,11 @@
     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 @@
         return 0;
     bc->setlocal = Saved->Prev;
+    bEnableExtensions = Saved->EnableExtensions;
     bDelayedExpansion = Saved->DelayedExpansion;
     /* First, clear out the environment. Since making any changes to the