Implement /CMDCONS switch, which allows the user to start in text mode
authorHervé Poussineau <hpoussin@reactos.org>
Fri, 4 Aug 2006 19:44:35 +0000 (19:44 +0000)
committerHervé Poussineau <hpoussin@reactos.org>
Fri, 4 Aug 2006 19:44:35 +0000 (19:44 +0000)
Autologon should only be done once (when starting the computer, not after the user has logged out)
Remove the status message dialog only in GUI

svn path=/trunk/; revision=23447

reactos/base/system/userinit/userinit.c
reactos/boot/bootdata/hivesft.inf
reactos/dll/win32/msgina/gui.c
reactos/dll/win32/msgina/msgina.c
reactos/dll/win32/msgina/msgina.h
reactos/dll/win32/msgina/tui.c

index b82a698..5a3f6a2 100644 (file)
@@ -21,6 +21,7 @@
  * PROJECT:     ReactOS Userinit Logon Application
  * FILE:        subsys/system/userinit/userinit.c
  * PROGRAMMERS: Thomas Weidenmueller (w3seek@users.sourceforge.net)
+ *              Hervé Poussineau (hpoussin@reactos.org)
  */
 #include <windows.h>
 #include <cfgmgr32.h>
 
 /* FUNCTIONS ****************************************************************/
 
+static LONG
+ReadRegSzKey(
+       IN HKEY hKey,
+       IN LPCWSTR pszKey,
+       OUT LPWSTR* pValue)
+{
+       LONG rc;
+       DWORD dwType;
+       DWORD cbData = 0;
+       LPWSTR Value;
+
+       rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
+       if (rc != ERROR_SUCCESS)
+               return rc;
+       if (dwType != REG_SZ)
+               return ERROR_FILE_NOT_FOUND;
+       Value = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
+       if (!Value)
+               return ERROR_NOT_ENOUGH_MEMORY;
+       rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)Value, &cbData);
+       if (rc != ERROR_SUCCESS)
+       {
+               HeapFree(GetProcessHeap(), 0, Value);
+               return rc;
+       }
+       /* NULL-terminate the string */
+       Value[cbData / sizeof(WCHAR)] = '\0';
+
+       *pValue = Value;
+       return ERROR_SUCCESS;
+}
+
+static
+BOOL IsConsoleShell(void)
+{
+       HKEY ControlKey = NULL;
+       LPWSTR SystemStartOptions = NULL;
+       LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */
+       LONG rc;
+       BOOL ret = FALSE;
+
+       rc = RegOpenKeyEx(
+               HKEY_LOCAL_MACHINE,
+               L"SYSTEM\\CurrentControlSet\\Control",
+               0,
+               KEY_QUERY_VALUE,
+               &ControlKey);
+
+       rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions);
+       if (rc != ERROR_SUCCESS)
+               goto cleanup;
+
+       /* Check for CMDCONS in SystemStartOptions */
+       CurrentOption = SystemStartOptions;
+       while (CurrentOption)
+       {
+               NextOption = wcschr(CurrentOption, L' ');
+               if (NextOption)
+                       *NextOption = L'\0';
+               if (wcsicmp(CurrentOption, L"CMDCONS") == 0)
+               {
+                       ret = TRUE;
+                       goto cleanup;
+               }
+               CurrentOption = NextOption ? NextOption + 1 : NULL;
+       }
+
+cleanup:
+       if (ControlKey != NULL)
+               RegCloseKey(ControlKey);
+       HeapFree(GetProcessHeap(), 0, SystemStartOptions);
+       return ret;
+}
+
 static
 BOOL GetShell(WCHAR *CommandLine)
 {
@@ -39,6 +114,7 @@ BOOL GetShell(WCHAR *CommandLine)
   DWORD Type, Size;
   WCHAR Shell[MAX_PATH];
   BOOL Ret = FALSE;
+  BOOL ConsoleShell = IsConsoleShell();
 
   if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
                   L"SOFTWARE\\ReactOS\\Windows NT\\CurrentVersion\\Winlogon",
@@ -46,7 +122,7 @@ BOOL GetShell(WCHAR *CommandLine)
   {
     Size = MAX_PATH * sizeof(WCHAR);
     if(RegQueryValueEx(hKey,
-                       L"Shell",
+                       ConsoleShell ? L"ConsoleShell" : L"Shell",
                        NULL,
                        &Type,
                        (LPBYTE)Shell,
@@ -63,10 +139,20 @@ BOOL GetShell(WCHAR *CommandLine)
 
   if(!Ret)
   {
-    if(GetWindowsDirectory(CommandLine, MAX_PATH - 13))
-      wcscat(CommandLine, L"\\explorer.exe");
+    if (ConsoleShell)
+    {
+      if(GetSystemDirectory(CommandLine, MAX_PATH - 8))
+        wcscat(CommandLine, L"\\cmd.exe");
+      else
+        wcscpy(CommandLine, L"cmd.exe");
+    }
     else
-      wcscpy(CommandLine, L"explorer.exe");
+    {
+      if(GetWindowsDirectory(CommandLine, MAX_PATH - 13))
+        wcscat(CommandLine, L"\\explorer.exe");
+      else
+        wcscpy(CommandLine, L"explorer.exe");
+    }
   }
 
   return Ret;
index 516849f..f259da8 100644 (file)
@@ -734,11 +734,10 @@ HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\Tonga Standard Tim
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
 
-;HKLM,"SOFTWARE\ReactOS\Windows NT\CurrentVersion\Winlogon","Shell",0x00020000,"%SystemRoot%\system32\cmd.exe"
+HKLM,"SOFTWARE\ReactOS\Windows NT\CurrentVersion\Winlogon","ConsoleShell",0x00020000,"%SystemRoot%\system32\cmd.exe"
 HKLM,"SOFTWARE\ReactOS\Windows NT\CurrentVersion\Winlogon","Shell",0x00020000,"%SystemRoot%\explorer.exe"
 HKLM,"SOFTWARE\ReactOS\Windows NT\CurrentVersion\Winlogon","StartServices",0x00010001,0x00000001
 HKLM,"SOFTWARE\ReactOS\Windows NT\CurrentVersion\Winlogon","StartLsass",0x00010001,0x00000001
-HKLM,"SOFTWARE\ReactOS\Windows NT\CurrentVersion\Winlogon","StartGUI",0x00010001,0x00000000
 HKLM,"SOFTWARE\ReactOS\Windows NT\CurrentVersion\Winlogon","Userinit",0x00020000,"%SystemRoot%\system32\userinit.exe"
 HKLM,"SOFTWARE\ReactOS\Windows NT\CurrentVersion\Winlogon","AutoAdminLogon",0x00000000,"1"
 HKLM,"SOFTWARE\ReactOS\Windows NT\CurrentVersion\Winlogon","DefaultUserName",0x00000000,"Administrator"
index b05a32c..da0ec2e 100644 (file)
@@ -148,6 +148,19 @@ GUIDisplayStatusMessage(
        return TRUE;\r
 }\r
 \r
+static BOOL\r
+GUIRemoveStatusMessage(\r
+       IN PGINA_CONTEXT pgContext)\r
+{\r
+       if (pgContext->hStatusWindow)\r
+       {\r
+               EndDialog(pgContext->hStatusWindow, 0);\r
+               pgContext->hStatusWindow = 0;\r
+       }\r
+\r
+       return TRUE;\r
+}\r
+\r
 static INT_PTR CALLBACK\r
 DisplaySASNoticeWindowProc(\r
        IN HWND hwndDlg,\r
@@ -390,6 +403,7 @@ GUILoggedOutSAS(
 GINA_UI GinaGraphicalUI = {\r
        GUIInitialize,\r
        GUIDisplayStatusMessage,\r
+       GUIRemoveStatusMessage,\r
        GUIDisplaySASNotice,\r
        GUILoggedOnSAS,\r
        GUILoggedOutSAS,\r
index 864d1d1..0f29c2b 100644 (file)
 
 #include "msgina.h"
 
+//#define YDEBUG
 #include <wine/debug.h>
 
 extern HINSTANCE hDllInstance;
 
 extern GINA_UI GinaGraphicalUI;
 extern GINA_UI GinaTextUI;
-static PGINA_UI pGinaUI = &GinaGraphicalUI; /* Default value */
+static PGINA_UI pGinaUI;
 
 /*
  * @implemented
@@ -52,41 +53,83 @@ WlxNegotiate(
        return TRUE;
 }
 
+static LONG
+ReadRegSzKey(
+       IN HKEY hKey,
+       IN LPCWSTR pszKey,
+       OUT LPWSTR* pValue)
+{
+       LONG rc;
+       DWORD dwType;
+       DWORD cbData = 0;
+       LPWSTR Value;
+
+       rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
+       if (rc != ERROR_SUCCESS)
+               return rc;
+       if (dwType != REG_SZ)
+               return ERROR_FILE_NOT_FOUND;
+       Value = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
+       if (!Value)
+               return ERROR_NOT_ENOUGH_MEMORY;
+       rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)Value, &cbData);
+       if (rc != ERROR_SUCCESS)
+       {
+               HeapFree(GetProcessHeap(), 0, Value);
+               return rc;
+       }
+       /* NULL-terminate the string */
+       Value[cbData / sizeof(WCHAR)] = '\0';
+
+       *pValue = Value;
+       return ERROR_SUCCESS;
+}
+
 static VOID
 ChooseGinaUI(VOID)
 {
-       HKEY WinLogonKey = NULL;
-       DWORD Type, Size, Value;
+       HKEY ControlKey = NULL;
+       LPWSTR SystemStartOptions = NULL;
+       LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */
+       BOOL ConsoleBoot = FALSE;
        LONG rc;
 
        rc = RegOpenKeyEx(
                HKEY_LOCAL_MACHINE,
-               L"SOFTWARE\\ReactOS\\Windows NT\\CurrentVersion\\WinLogon",
+               L"SYSTEM\\CurrentControlSet\\Control",
                0,
                KEY_QUERY_VALUE,
-               &WinLogonKey);
+               &ControlKey);
+
+       rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions);
        if (rc != ERROR_SUCCESS)
                goto cleanup;
 
-       Size = sizeof(DWORD);
-       rc = RegQueryValueEx(
-               WinLogonKey,
-               L"StartGUI",
-               NULL,
-               &Type,
-               (LPBYTE)&Value,
-               &Size);
-       if (rc != ERROR_SUCCESS || Type != REG_DWORD || Size != sizeof(DWORD))
-               goto cleanup;
+       /* Check for CMDCONS in SystemStartOptions */
+       CurrentOption = SystemStartOptions;
+       while (CurrentOption)
+       {
+               NextOption = wcschr(CurrentOption, L' ');
+               if (NextOption)
+                       *NextOption = L'\0';
+               if (wcsicmp(CurrentOption, L"CMDCONS") == 0)
+               {
+                       TRACE("Found %S. Switching to console boot\n", CurrentOption);
+                       ConsoleBoot = TRUE;
+                       goto cleanup;
+               }
+               CurrentOption = NextOption ? NextOption + 1 : NULL;
+       }
 
-       if (Value != 0)
-               pGinaUI = &GinaGraphicalUI;
-       else
+cleanup:
+       if (ConsoleBoot)
                pGinaUI = &GinaTextUI;
+       else
+               pGinaUI = &GinaGraphicalUI;
 
-cleanup:
-       if (WinLogonKey != NULL)
-               RegCloseKey(WinLogonKey);
+       if (ControlKey != NULL)
+               RegCloseKey(ControlKey);
+       HeapFree(GetProcessHeap(), 0, SystemStartOptions);
 }
 
 /*
@@ -129,7 +172,7 @@ WlxInitialize(
   /* Locates the authentification package */
   //LsaRegisterLogonProcess(...);
 
-  pgContext->DoAutoLogonOnce = FALSE;
+  pgContext->AutoLogonState = AUTOLOGON_CHECK_REGISTRY;
 
   ChooseGinaUI();
   return pGinaUI->Initialize(pgContext);
@@ -290,45 +333,10 @@ WlxRemoveStatusMessage(
        IN PVOID pWlxContext)
 {
        PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
-       if (pgContext->hStatusWindow)
-       {
-               EndDialog(pgContext->hStatusWindow, 0);
-               pgContext->hStatusWindow = 0;
-       }
-
-       return TRUE;
-}
-
-static LONG
-ReadRegSzKey(
-       IN HKEY hKey,
-       IN LPCWSTR pszKey,
-       OUT LPWSTR* pValue)
-{
-       LONG rc;
-       DWORD dwType;
-       DWORD cbData = 0;
-       LPWSTR Value;
 
-       rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
-       if (rc != ERROR_SUCCESS)
-               return rc;
-       if (dwType != REG_SZ)
-               return ERROR_FILE_NOT_FOUND;
-       Value = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
-       if (!Value)
-               return ERROR_NOT_ENOUGH_MEMORY;
-       rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)Value, &cbData);
-       if (rc != ERROR_SUCCESS)
-       {
-               HeapFree(GetProcessHeap(), 0, Value);
-               return rc;
-       }
-       /* NULL-terminate the string */
-       Value[cbData / sizeof(WCHAR)] = '\0';
+       TRACE("WlxRemoveStatusMessage()\n");
 
-       *pValue = Value;
-       return ERROR_SUCCESS;
+       return pGinaUI->RemoveStatusMessage(pgContext);
 }
 
 static PWSTR
@@ -394,8 +402,7 @@ DoLoginTasks(
 
 static BOOL
 DoAutoLogon(
-       IN PGINA_CONTEXT pgContext,
-       IN BOOL CheckOnly)
+       IN PGINA_CONTEXT pgContext)
 {
        HKEY WinLogonKey = NULL;
        LPWSTR AutoLogon = NULL;
@@ -407,6 +414,12 @@ DoAutoLogon(
        BOOL result = FALSE;
        LONG rc;
 
+       TRACE("DoAutoLogon(): AutoLogonState = %lu\n",
+               pgContext->AutoLogonState);
+
+       if (pgContext->AutoLogonState == AUTOLOGON_DISABLED)
+               return FALSE;
+
        rc = RegOpenKeyEx(
                HKEY_LOCAL_MACHINE,
                L"SOFTWARE\\ReactOS\\Windows NT\\CurrentVersion\\WinLogon",
@@ -416,47 +429,54 @@ DoAutoLogon(
        if (rc != ERROR_SUCCESS)
                goto cleanup;
 
-       rc = ReadRegSzKey(WinLogonKey, L"AutoAdminLogon", &AutoLogon);
-       if (rc != ERROR_SUCCESS)
-               goto cleanup;
-       if (wcscmp(AutoLogon, L"1") != 0)
-               goto cleanup;
+       if (pgContext->AutoLogonState == AUTOLOGON_CHECK_REGISTRY)
+       {
+               /* Set it by default to disabled, we might reenable it again later */
+               pgContext->AutoLogonState = AUTOLOGON_DISABLED;
 
-       rc = ReadRegSzKey(WinLogonKey, L"AutoLogonCount", &AutoCount);
-       if (rc == ERROR_SUCCESS && wcscmp(AutoCount, L"0") == 0)
-               goto cleanup;
-       else if (rc != ERROR_FILE_NOT_FOUND)
-               goto cleanup;
+               rc = ReadRegSzKey(WinLogonKey, L"AutoAdminLogon", &AutoLogon);
+               if (rc != ERROR_SUCCESS)
+                       goto cleanup;
+               if (wcscmp(AutoLogon, L"1") != 0)
+                       goto cleanup;
 
-       rc = ReadRegSzKey(WinLogonKey, L"IgnoreShiftOverride", &UserName);
-       if (rc == ERROR_SUCCESS)
-       {
-               if (wcscmp(AutoLogon, L"1") != 0 && GetKeyState(VK_SHIFT) < 0)
+               rc = ReadRegSzKey(WinLogonKey, L"AutoLogonCount", &AutoCount);
+               if (rc == ERROR_SUCCESS && wcscmp(AutoCount, L"0") == 0)
+                       goto cleanup;
+               else if (rc != ERROR_FILE_NOT_FOUND)
                        goto cleanup;
-       }
-       else if (GetKeyState(VK_SHIFT) < 0)
-       {
-               /* User pressed SHIFT */
-               goto cleanup;
-       }
 
-       if (CheckOnly)
-       {
+               rc = ReadRegSzKey(WinLogonKey, L"IgnoreShiftOverride", &UserName);
+               if (rc == ERROR_SUCCESS)
+               {
+                       if (wcscmp(AutoLogon, L"1") != 0 && GetKeyState(VK_SHIFT) < 0)
+                               goto cleanup;
+               }
+               else if (GetKeyState(VK_SHIFT) < 0)
+               {
+                       /* User pressed SHIFT */
+                       goto cleanup;
+               }
+
+               pgContext->AutoLogonState = AUTOLOGON_ONCE;
                result = TRUE;
-               goto cleanup;
        }
+       else /* pgContext->AutoLogonState == AUTOLOGON_ONCE */
+       {
+               pgContext->AutoLogonState = AUTOLOGON_DISABLED;
 
-       rc = ReadRegSzKey(WinLogonKey, L"DefaultUserName", &UserName);
-       if (rc != ERROR_SUCCESS)
-               goto cleanup;
-       rc = ReadRegSzKey(WinLogonKey, L"DefaultDomainName", &DomainName);
-       if (rc != ERROR_SUCCESS && rc != ERROR_FILE_NOT_FOUND)
-               goto cleanup;
-       rc = ReadRegSzKey(WinLogonKey, L"DefaultPassword", &Password);
-       if (rc != ERROR_SUCCESS)
-               goto cleanup;
+               rc = ReadRegSzKey(WinLogonKey, L"DefaultUserName", &UserName);
+               if (rc != ERROR_SUCCESS)
+                       goto cleanup;
+               rc = ReadRegSzKey(WinLogonKey, L"DefaultDomainName", &DomainName);
+               if (rc != ERROR_SUCCESS && rc != ERROR_FILE_NOT_FOUND)
+                       goto cleanup;
+               rc = ReadRegSzKey(WinLogonKey, L"DefaultPassword", &Password);
+               if (rc != ERROR_SUCCESS)
+                       goto cleanup;
 
-       result = DoLoginTasks(pgContext, UserName, DomainName, Password);
+               result = DoLoginTasks(pgContext, UserName, DomainName, Password);
+       }
 
 cleanup:
        if (WinLogonKey != NULL)
@@ -467,6 +487,8 @@ cleanup:
        HeapFree(GetProcessHeap(), 0, UserName);
        HeapFree(GetProcessHeap(), 0, DomainName);
        HeapFree(GetProcessHeap(), 0, Password);
+       TRACE("DoAutoLogon(): AutoLogonState = %lu, returning %d\n",
+               pgContext->AutoLogonState, result);
        return result;
 }
 
@@ -488,13 +510,15 @@ WlxDisplaySASNotice(
                return;
        }
 
-       if (DoAutoLogon(NULL, TRUE))
+       if (DoAutoLogon(pgContext))
        {
                /* Don't display the window, we want to do an automatic logon */
-               pgContext->DoAutoLogonOnce = TRUE;
+               pgContext->AutoLogonState = AUTOLOGON_ONCE;
                pgContext->pWlxFuncs->WlxSasNotify(pgContext->hWlx, WLX_SAS_TYPE_CTRL_ALT_DEL);
                return;
        }
+       else
+               pgContext->AutoLogonState = AUTOLOGON_DISABLED;
 
        pGinaUI->DisplaySASNotice(pgContext);
 
@@ -526,12 +550,10 @@ WlxLoggedOutSAS(
        pgContext->pProfile = pProfile;
 
        if (!GetSystemMetrics(SM_REMOTESESSION) &&
-           pgContext->DoAutoLogonOnce &&
-           DoAutoLogon(pgContext, FALSE))
+           DoAutoLogon(pgContext))
        {
                /* User is local and registry contains information
                 * to log on him automatically */
-               pgContext->DoAutoLogonOnce = FALSE;
                return WLX_SAS_ACTION_LOGON;
        }
 
index 621b93a..47aae41 100644 (file)
@@ -5,7 +5,13 @@
 #include <winwlx.h>
 #include "resource.h"
 
-typedef struct {
+/* Values for GINA_CONTEXT.AutoLogonState */
+#define AUTOLOGON_CHECK_REGISTRY 1
+#define AUTOLOGON_ONCE           2
+#define AUTOLOGON_DISABLED       3
+
+typedef struct
+{
        HANDLE hWlx;
        LPWSTR station;
        PWLX_DISPATCH_VERSION_1_3 pWlxFuncs;
@@ -13,7 +19,7 @@ typedef struct {
        HANDLE UserToken;
        HWND hStatusWindow;
        BOOL SignaledStatusWindowCreated;
-       BOOL DoAutoLogonOnce;
+       DWORD AutoLogonState;
 
        /* Informations to be filled during logon */
        PLUID pAuthenticationId;
@@ -30,6 +36,7 @@ HINSTANCE hDllInstance;
 
 typedef BOOL (*PFGINA_INITIALIZE)(PGINA_CONTEXT);
 typedef BOOL (*PFGINA_DISPLAYSTATUSMESSAGE)(PGINA_CONTEXT, HDESK, DWORD, PWSTR, PWSTR);
+typedef BOOL (*PFGINA_REMOVESTATUSMESSAGE)(PGINA_CONTEXT);
 typedef VOID (*PFGINA_DISPLAYSASNOTICE)(PGINA_CONTEXT);
 typedef INT (*PFGINA_LOGGEDONSAS)(PGINA_CONTEXT, DWORD);
 typedef INT (*PFGINA_LOGGEDOUTSAS)(PGINA_CONTEXT);
@@ -37,6 +44,7 @@ typedef struct _GINA_UI
 {
        PFGINA_INITIALIZE Initialize;
        PFGINA_DISPLAYSTATUSMESSAGE DisplayStatusMessage;
+       PFGINA_REMOVESTATUSMESSAGE RemoveStatusMessage;
        PFGINA_DISPLAYSASNOTICE DisplaySASNotice;
        PFGINA_LOGGEDONSAS LoggedOnSAS;
        PFGINA_LOGGEDOUTSAS LoggedOutSAS;
index 2c0d00c..b9191dc 100644 (file)
@@ -47,6 +47,14 @@ TUIDisplayStatusMessage(
                        NULL);\r
 }\r
 \r
+static BOOL\r
+TUIRemoveStatusMessage(\r
+       IN PGINA_CONTEXT pgContext)\r
+{\r
+       /* Nothing to do */\r
+       return TRUE;\r
+}\r
+\r
 static VOID\r
 TUIDisplaySASNotice(\r
        IN OUT PGINA_CONTEXT pgContext)\r
@@ -145,6 +153,7 @@ TUILoggedOutSAS(
 GINA_UI GinaTextUI = {\r
        TUIInitialize,\r
        TUIDisplayStatusMessage,\r
+       TUIRemoveStatusMessage,\r
        TUIDisplaySASNotice,\r
        TUILoggedOnSAS,\r
        TUILoggedOutSAS,\r