[WINLOGON]
[reactos.git] / reactos / base / system / winlogon / winlogon.c
index 5cc8fd8..3329848 100644 (file)
-/* $Id$
- *
+/*
  * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
- * FILE:            services/winlogon/winlogon.c
+ * PROJECT:         ReactOS Winlogon
+ * FILE:            base/system/winlogon/winlogon.c
  * PURPOSE:         Logon
- * PROGRAMMER:      David Welch (welch@cwcom.net)
- * UPDATE HISTORY:
- *                  Created 22/05/98
+ * PROGRAMMERS:     Thomas Weidenmueller (w3seek@users.sourceforge.net)
+ *                  Filip Navara
+ *                  HervĂ© Poussineau (hpoussin@reactos.org)
  */
 
 /* INCLUDES *****************************************************************/
+
 #include "winlogon.h"
 
-#define NDEBUG
-#include <debug.h>
+#include <wine/debug.h>
 
-#define SUPPORT_CONSOLESTART 1
-#define START_LSASS          1
+WINE_DEFAULT_DEBUG_CHANNEL(winlogon);
 
 /* GLOBALS ******************************************************************/
 
-BOOL
-LoadGina(PMSGINAFUNCTIONS Functions, DWORD *DllVersion);
-PWLSESSION
-MsGinaInit(void);
-void
-SessionLoop(PWLSESSION Session);
-BOOL
-InitServices(void);
-BOOL
-WlxCreateWindowStationAndDesktops(PWLSESSION Session);
-
 HINSTANCE hAppInstance;
 PWLSESSION WLSession = NULL;
 
-#if SUPPORT_CONSOLESTART
-BOOL StartConsole = TRUE;
-#endif
-
 /* FUNCTIONS *****************************************************************/
 
-static void
-PrintString (WCHAR* fmt,...)
-{
-   WCHAR buffer[512];
-   va_list ap;
-
-   va_start(ap, fmt);
-   wsprintf(buffer, fmt, ap);
-   va_end(ap);
-
-   OutputDebugString(buffer);
-}
-
-
-INT_PTR CALLBACK
-ShutdownComputerProc (HWND hwndDlg,
-                     UINT uMsg,
-                     WPARAM wParam,
-                     LPARAM lParam)
+DWORD
+WINAPI
+PlayLogonSoundThread(
+       IN LPVOID lpParameter)
 {
-  switch(uMsg)
-  {
-    case WM_COMMAND:
-    {
-      switch(LOWORD(wParam))
-      {
-        case IDC_BTNSHTDOWNCOMPUTER:
-          EndDialog(hwndDlg, IDC_BTNSHTDOWNCOMPUTER);
-          break;
-      }
-      break;
-    }
-    case WM_INITDIALOG:
-    {
-      RemoveMenu(GetSystemMenu(hwndDlg, FALSE), SC_CLOSE, MF_BYCOMMAND);
-      SetFocus(GetDlgItem(hwndDlg, IDC_BTNSHTDOWNCOMPUTER));
-      break;
-    }
-  }
-  return FALSE;
+       HKEY hKey;
+       WCHAR szBuffer[MAX_PATH] = {0};
+       WCHAR szDest[MAX_PATH];
+       DWORD dwSize = sizeof(szBuffer);
+       HMODULE hLibrary;
+       SERVICE_STATUS_PROCESS Info;
+       typedef BOOL (WINAPI *PLAYSOUNDW)(LPCWSTR,HMODULE,DWORD);
+       PLAYSOUNDW Play;
+       ULONG Index = 0;
+
+       if (RegOpenKeyExW(HKEY_CURRENT_USER, L"AppEvents\\Schemes\\Apps\\.Default\\WindowsLogon\\.Current", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
+       {
+               ExitThread(0);
+       }
+
+       if (RegQueryValueExW(hKey, NULL, NULL, NULL, (LPBYTE)szBuffer, &dwSize) != ERROR_SUCCESS)
+       {
+               RegCloseKey(hKey);
+               ExitThread(0);
+       }
+
+
+       RegCloseKey(hKey);
+
+       if (!szBuffer[0])
+               ExitThread(0);
+
+
+       szBuffer[MAX_PATH-1] = L'\0';
+       if (ExpandEnvironmentStringsW(szBuffer, szDest, MAX_PATH))
+       {
+               SC_HANDLE hSCManager, hService;
+
+               hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
+               if (!hSCManager)
+                       ExitThread(0);;
+
+               hService = OpenServiceW(hSCManager, L"wdmaud", GENERIC_READ);
+               if (!hService)
+               {
+                       CloseServiceHandle(hSCManager);
+                       TRACE("WL: failed to open sysaudio Status %x\n", GetLastError());
+                       ExitThread(0);
+               }
+
+               do
+               {
+                       if (!QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&Info, sizeof(SERVICE_STATUS_PROCESS), &dwSize))
+                       {
+                               TRACE("WL: QueryServiceStatusEx failed %x\n", GetLastError());
+                               break;
+                       }
+
+                       if (Info.dwCurrentState == SERVICE_RUNNING)
+                               break;
+
+                       Sleep(1000);
+
+               }while(Index++ < 20);
+
+               CloseServiceHandle(hService);
+               CloseServiceHandle(hSCManager);
+
+               if (Info.dwCurrentState != SERVICE_RUNNING)
+                       ExitThread(0);
+
+
+               hLibrary = LoadLibraryW(L"winmm.dll");
+               if (hLibrary)
+               {
+                       Play = (PLAYSOUNDW)GetProcAddress(hLibrary, "PlaySoundW");
+                       if (Play)
+                       {
+                               Play(szDest, NULL, SND_FILENAME);
+                       }
+                       FreeLibrary(hLibrary);
+               }
+       }
+       ExitThread(0);
 }
 
-static BOOLEAN
-StartServices (VOID)
-{
-   HANDLE ServicesInitEvent;
-   BOOLEAN Result;
-   STARTUPINFO StartupInfo;
-   PROCESS_INFORMATION ProcessInformation;
-   DWORD Count;
-   WCHAR ServiceString[] = L"services.exe";
-
-   /* Start the service control manager (services.exe) */
-
-   StartupInfo.cb = sizeof(StartupInfo);
-   StartupInfo.lpReserved = NULL;
-   StartupInfo.lpDesktop = NULL;
-   StartupInfo.lpTitle = NULL;
-   StartupInfo.dwFlags = 0;
-   StartupInfo.cbReserved2 = 0;
-   StartupInfo.lpReserved2 = 0;
 
-#if 0
-   PrintString(L"WL: Creating new process - \"services.exe\".\n");
-#endif
-
-   Result = CreateProcess(NULL,
-                          ServiceString,
-                          NULL,
-                          NULL,
-                          FALSE,
-                          DETACHED_PROCESS,
-                          NULL,
-                          NULL,
-                          &StartupInfo,
-                          &ProcessInformation);
-   if (!Result)
-     {
-        PrintString(L"WL: Failed to execute services\n");
-        return FALSE;
-     }
-
-   /* wait for event creation (by SCM) for max. 20 seconds */
-   for (Count = 0; Count < 20; Count++)
-     {
-        Sleep(1000);
-
-        //DbgPrint("WL: Attempting to open event \"SvcctrlStartEvent_A3725DX\"\n");
-        ServicesInitEvent = OpenEvent(EVENT_ALL_ACCESS, //SYNCHRONIZE,
-                                      FALSE,
-                                      L"SvcctrlStartEvent_A3725DX");
-        if (ServicesInitEvent != NULL)
-          {
-             break;
-          }
-     }
-
-   if (ServicesInitEvent == NULL)
-     {
-        DbgPrint("WL: Failed to open event \"SvcctrlStartEvent_A3725DX\"\n");
-        return FALSE;
-     }
-
-   /* wait for event signalization */
-   //DbgPrint("WL: Waiting forever on event handle: %x\n", ServicesInitEvent);
-   WaitForSingleObject(ServicesInitEvent, INFINITE);
-   //DbgPrint("WL: Closing event object \"SvcctrlStartEvent_A3725DX\"\n");
-   CloseHandle(ServicesInitEvent);
-   //DbgPrint("WL: StartServices() Done.\n");
-
-   return TRUE;
-}
 
-#if START_LSASS
-static BOOLEAN
-StartLsass (VOID)
+static BOOL
+StartServicesManager(VOID)
 {
-   HANDLE LsassInitEvent;
-   BOOLEAN Result;
-   STARTUPINFO StartupInfo;
-   PROCESS_INFORMATION ProcessInformation;
-   WCHAR ServiceString[] = L"lsass.exe";
-
-   LsassInitEvent = CreateEvent(NULL,
-                                TRUE,
-                                FALSE,
-                                L"\\SECURITY_SERVICES_STARTED");
-
-   if (LsassInitEvent == NULL)
-     {
-        DbgPrint("WL: Failed to create lsass notification event\n");
-        return(FALSE);
-     }
-
-   /* Start the local security authority subsystem (lsass.exe) */
-
-   StartupInfo.cb = sizeof(StartupInfo);
-   StartupInfo.lpReserved = NULL;
-   StartupInfo.lpDesktop = NULL;
-   StartupInfo.lpTitle = NULL;
-   StartupInfo.dwFlags = 0;
-   StartupInfo.cbReserved2 = 0;
-   StartupInfo.lpReserved2 = 0;
-
-   Result = CreateProcess(NULL,
-                          ServiceString,
-                          NULL,
-                          NULL,
-                          FALSE,
-                          DETACHED_PROCESS,
-                          NULL,
-                          NULL,
-                          &StartupInfo,
-                          &ProcessInformation);
-   if (!Result)
-     {
-        DbgPrint("WL: Failed to execute lsass\n");
-        return(FALSE);
-     }
-
-   WaitForSingleObject(LsassInitEvent, INFINITE);
-   CloseHandle(LsassInitEvent);
-
-   return(TRUE);
+       STARTUPINFOW StartupInfo;
+       PROCESS_INFORMATION ProcessInformation;
+       LPCWSTR ServiceString = L"services.exe";
+       BOOL res;
+
+       /* Start the service control manager (services.exe) */
+       ZeroMemory(&StartupInfo, sizeof(STARTUPINFOW));
+       StartupInfo.cb = sizeof(StartupInfo);
+       StartupInfo.lpReserved = NULL;
+       StartupInfo.lpDesktop = NULL;
+       StartupInfo.lpTitle = NULL;
+       StartupInfo.dwFlags = 0;
+       StartupInfo.cbReserved2 = 0;
+       StartupInfo.lpReserved2 = 0;
+
+       TRACE("WL: Creating new process - %S\n", ServiceString);
+
+       res = CreateProcessW(
+               ServiceString,
+               NULL,
+               NULL,
+               NULL,
+               FALSE,
+               DETACHED_PROCESS,
+               NULL,
+               NULL,
+               &StartupInfo,
+               &ProcessInformation);
+       if (!res)
+       {
+               ERR("WL: Failed to execute services (error %lu)\n", GetLastError());
+               return FALSE;
+       }
+
+       TRACE("WL: Created new process - %S\n", ServiceString);
+
+       CloseHandle(ProcessInformation.hThread);
+       CloseHandle(ProcessInformation.hProcess);
+
+       TRACE("WL: StartServicesManager() done.\n");
+
+       return TRUE;
 }
-#endif
 
 
-static BOOLEAN
-OpenRegistryKey (HKEY *WinLogonKey)
+static BOOL
+StartLsass(VOID)
 {
-   return ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-                                        L"SOFTWARE\\ReactOS\\Windows NT\\CurrentVersion\\WinLogon",
-                                        0,
-                                        KEY_QUERY_VALUE,
-                                        WinLogonKey);
+       STARTUPINFOW StartupInfo;
+       PROCESS_INFORMATION ProcessInformation;
+       LPCWSTR ServiceString = L"lsass.exe";
+       BOOL res;
+
+       /* Start the service control manager (services.exe) */
+       ZeroMemory(&StartupInfo, sizeof(STARTUPINFOW));
+       StartupInfo.cb = sizeof(StartupInfo);
+       StartupInfo.lpReserved = NULL;
+       StartupInfo.lpDesktop = NULL;
+       StartupInfo.lpTitle = NULL;
+       StartupInfo.dwFlags = 0;
+       StartupInfo.cbReserved2 = 0;
+       StartupInfo.lpReserved2 = 0;
+
+       TRACE("WL: Creating new process - %S\n", ServiceString);
+
+       res = CreateProcessW(
+               ServiceString,
+               NULL,
+               NULL,
+               NULL,
+               FALSE,
+               DETACHED_PROCESS,
+               NULL,
+               NULL,
+               &StartupInfo,
+               &ProcessInformation);
+
+       TRACE("WL: Created new process - %S\n", ServiceString);
+
+       CloseHandle(ProcessInformation.hThread);
+       CloseHandle(ProcessInformation.hProcess);
+
+       return res;
 }
 
-
-static BOOLEAN StartProcess(PWCHAR ValueName)
+BOOL
+DisplayStatusMessage(
+       IN PWLSESSION Session,
+       IN HDESK hDesktop,
+       IN UINT ResourceId)
 {
-   BOOL StartIt;
-   HKEY WinLogonKey;
-   DWORD Type;
-   DWORD Size;
-   DWORD StartValue;
-
-   StartIt = TRUE;
-   if (OpenRegistryKey(&WinLogonKey))
-     {
-       Size = sizeof(DWORD);
-       if (ERROR_SUCCESS == RegQueryValueEx(WinLogonKey,
-                                             ValueName,
-                                            NULL,
-                                            &Type,
-                                            (LPBYTE) &StartValue,
-                                             &Size))
-          {
-          if (REG_DWORD == Type)
-            {
-               StartIt = (0 != StartValue);
-            }
-          }
-       RegCloseKey(WinLogonKey);
-     }
-
-   return StartIt;
-}
+       WCHAR StatusMsg[MAX_PATH];
 
-/*
-static BOOL RestartShell(void)
-{
-  HKEY WinLogonKey;
-  DWORD Type, Size, Value;
-
-  if(OpenRegistryKey(&WinLogonKey))
-  {
-    Size = sizeof(DWORD);
-    if(ERROR_SUCCESS == RegQueryValueEx(WinLogonKey,
-                                        L"AutoRestartShell",
-                                        NULL,
-                                        &Type,
-                                        (LPBYTE)&Value,
-                                        &Size))
-    {
-      if(Type == REG_DWORD)
-      {
-        RegCloseKey(WinLogonKey);
-        return (Value != 0);
-      }
-    }
-    RegCloseKey(WinLogonKey);
-  }
-  return FALSE;
-}
-*/
+       if (Session->Gina.Version < WLX_VERSION_1_3)
+               return TRUE;
 
-VOID STDCALL
-RegisterHotKeys(VOID)
-{
-  RegisterHotKey(NULL, 0, MOD_ALT | MOD_CONTROL, VK_DELETE);
-}
+       if (Session->SuppressStatus)
+               return TRUE;
 
-VOID STDCALL
-UnregisterHotKeys(VOID)
-{
-  UnregisterHotKey(NULL, 0);
-}
+       if (LoadStringW(hAppInstance, ResourceId, StatusMsg, MAX_PATH) == 0)
+               return FALSE;
 
-VOID STDCALL
-HandleHotKey(MSG *Msg)
-{
-  DbgPrint("HOTKEY: Got hot key (%d)\n", Msg->wParam);
-
-  /* CTRL-ALT-DEL */
-  if (Msg->wParam == 0)
-  {
-    STARTUPINFO StartupInfo;
-    PROCESS_INFORMATION ProcessInformation;
-
-    StartupInfo.cb = sizeof(StartupInfo);
-    StartupInfo.lpReserved = NULL;
-    StartupInfo.lpDesktop = NULL;
-    StartupInfo.lpTitle = NULL;
-    StartupInfo.dwFlags = 0;
-    StartupInfo.cbReserved2 = 0;
-    StartupInfo.lpReserved2 = 0;
-
-    CreateProcessW(
-      L"taskmgr.exe",
-      NULL,
-      NULL,
-      NULL,
-      FALSE,
-      CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS,
-      NULL,
-      NULL,
-      &StartupInfo,
-      &ProcessInformation);
-
-    CloseHandle (ProcessInformation.hProcess);
-    CloseHandle (ProcessInformation.hThread);
-  }
+       return Session->Gina.Functions.WlxDisplayStatusMessage(Session->Gina.Context, hDesktop, 0, NULL, StatusMsg);
 }
 
-#if SUPPORT_CONSOLESTART
-static BOOL StartIntoGUI(VOID)
+BOOL
+RemoveStatusMessage(
+       IN PWLSESSION Session)
 {
-  HKEY WinLogonKey;
-  DWORD Type, Size, Value;
-
-  if(OpenRegistryKey(&WinLogonKey))
-  {
-    Size = sizeof(DWORD);
-    if(ERROR_SUCCESS == RegQueryValueEx(WinLogonKey,
-                                        L"StartGUI",
-                                        NULL,
-                                        &Type,
-                                        (LPBYTE)&Value,
-                                        &Size))
-    {
-      if(Type == REG_DWORD)
-      {
-        RegCloseKey(WinLogonKey);
-        return (Value != 0);
-      }
-    }
-    RegCloseKey(WinLogonKey);
-  }
-  return FALSE;
-}
-
+       if (Session->Gina.Version < WLX_VERSION_1_3)
+               return TRUE;
 
-static PWCHAR
-GetUserInit (WCHAR *CommandLine)
-{
-   HKEY WinLogonKey;
-   BOOL GotCommandLine;
-   DWORD Type;
-   DWORD Size;
-   WCHAR Shell[_MAX_PATH];
-
-   GotCommandLine = FALSE;
-   if (OpenRegistryKey(&WinLogonKey))
-     {
-       Size = MAX_PATH;
-       if (ERROR_SUCCESS == RegQueryValueEx(WinLogonKey,
-                                         L"UserInit",
-                                            NULL,
-                                            &Type,
-                                            (LPBYTE) Shell,
-                                         &Size))
-          {
-          if (REG_EXPAND_SZ == Type)
-            {
-               ExpandEnvironmentStrings(Shell, CommandLine, _MAX_PATH);
-               GotCommandLine = TRUE;
-            }
-          else if (REG_SZ == Type)
-            {
-               wcscpy(CommandLine, Shell);
-               GotCommandLine = TRUE;
-            }
-          }
-       RegCloseKey(WinLogonKey);
-     }
-
-   if (! GotCommandLine)
-     {
-       GetSystemDirectory(CommandLine, MAX_PATH - 15);
-       wcscat(CommandLine, L"\\userinit.exe");
-     }
-
-   return CommandLine;
+       return Session->Gina.Functions.WlxRemoveStatusMessage(Session->Gina.Context);
 }
 
-
-static BOOL
-DoLogonUser (PWCHAR Name,
-            PWCHAR Password)
+static INT_PTR CALLBACK
+GinaLoadFailedWindowProc(
+       IN HWND hwndDlg,
+       IN UINT uMsg,
+       IN WPARAM wParam,
+       IN LPARAM lParam)
 {
-  PROCESS_INFORMATION ProcessInformation;
-  STARTUPINFO StartupInfo;
-  WCHAR CommandLine[MAX_PATH];
-  WCHAR CurrentDirectory[MAX_PATH];
-  PROFILEINFOW ProfileInfo;
-  BOOL Result;
-  LPVOID lpEnvironment = NULL;
-  MSG Msg;
-
-  Result = LogonUserW (Name,
-                      NULL,
-                      Password,
-                      LOGON32_LOGON_INTERACTIVE,
-                      LOGON32_PROVIDER_DEFAULT,
-                      &WLSession->UserToken);
-  if (!Result)
-    {
-      DbgPrint ("WL: LogonUserW() failed\n");
-      RtlDestroyEnvironment (lpEnvironment);
-      return FALSE;
-    }
-
-  /* Load the user profile */
-  ProfileInfo.dwSize = sizeof(PROFILEINFOW);
-  ProfileInfo.dwFlags = 0;
-  ProfileInfo.lpUserName = Name;
-  ProfileInfo.lpProfilePath = NULL;
-  ProfileInfo.lpDefaultPath = NULL;
-  ProfileInfo.lpServerName = NULL;
-  ProfileInfo.lpPolicyPath = NULL;
-  ProfileInfo.hProfile = NULL;
-
-  if (!LoadUserProfileW (WLSession->UserToken,
-                        &ProfileInfo))
-    {
-      DbgPrint ("WL: LoadUserProfileW() failed\n");
-      CloseHandle (WLSession->UserToken);
-      RtlDestroyEnvironment (lpEnvironment);
-      return FALSE;
-    }
-
-  if (!CreateEnvironmentBlock (&lpEnvironment,
-                              WLSession->UserToken,
-                              TRUE))
-    {
-      DbgPrint ("WL: CreateEnvironmentBlock() failed\n");
-      return FALSE;
-    }
-
-  if (ImpersonateLoggedOnUser(WLSession->UserToken))
-    {
-      UpdatePerUserSystemParameters(0, TRUE);
-      RevertToSelf();
-    }
-
-  GetWindowsDirectoryW (CurrentDirectory, MAX_PATH);
-
-  StartupInfo.cb = sizeof(StartupInfo);
-  StartupInfo.lpReserved = NULL;
-  StartupInfo.lpDesktop = NULL;
-  StartupInfo.lpTitle = NULL;
-  StartupInfo.dwFlags = 0;
-  StartupInfo.cbReserved2 = 0;
-  StartupInfo.lpReserved2 = 0;
-
-  Result = CreateProcessAsUserW (WLSession->UserToken,
-                                NULL,
-                                GetUserInit (CommandLine),
-                                NULL,
-                                NULL,
-                                FALSE,
-                                CREATE_UNICODE_ENVIRONMENT,
-                                lpEnvironment,
-                                CurrentDirectory,
-                                &StartupInfo,
-                                &ProcessInformation);
-  if (!Result)
-    {
-      DbgPrint ("WL: Failed to execute user shell %s\n", CommandLine);
-      if (ImpersonateLoggedOnUser(WLSession->UserToken))
-        {
-          UpdatePerUserSystemParameters(0, FALSE);
-          RevertToSelf();
-        }
-      UnloadUserProfile (WLSession->UserToken,
-                        ProfileInfo.hProfile);
-      CloseHandle (WLSession->UserToken);
-      DestroyEnvironmentBlock (lpEnvironment);
-      return FALSE;
-    }
-
-  RegisterHotKeys();
-
-  while (WaitForSingleObject (ProcessInformation.hProcess, 100) != WAIT_OBJECT_0)
-  {
-    if (PeekMessage(&Msg, 0, 0, 0, PM_REMOVE))
-    {
-      if (Msg.message == WM_HOTKEY)
-        HandleHotKey(&Msg);
-      TranslateMessage(&Msg);
-      DispatchMessage(&Msg);
-    }
-  }
-
-  UnregisterHotKeys();
-
-  CloseHandle (ProcessInformation.hProcess);
-  CloseHandle (ProcessInformation.hThread);
-
-  if (ImpersonateLoggedOnUser(WLSession->UserToken))
-    {
-      UpdatePerUserSystemParameters(0, FALSE);
-      RevertToSelf();
-    }
-
-  /* Unload user profile */
-  UnloadUserProfile (WLSession->UserToken,
-                    ProfileInfo.hProfile);
-
-  CloseHandle (WLSession->UserToken);
-
-  RtlDestroyEnvironment (lpEnvironment);
-
-  return TRUE;
+       switch (uMsg)
+       {
+               case WM_COMMAND:
+               {
+                       switch (LOWORD(wParam))
+                       {
+                               case IDOK:
+                                       EndDialog(hwndDlg, IDOK);
+                                       return TRUE;
+                       }
+                       break;
+               }
+               case WM_INITDIALOG:
+               {
+                       int len;
+                       WCHAR templateText[MAX_PATH], text[MAX_PATH];
+
+                       len = GetDlgItemTextW(hwndDlg, IDC_GINALOADFAILED, templateText, MAX_PATH);
+                       if (len)
+                       {
+                               wsprintfW(text, templateText, (LPWSTR)lParam);
+                               SetDlgItemTextW(hwndDlg, IDC_GINALOADFAILED, text);
+                       }
+                       SetFocus(GetDlgItem(hwndDlg, IDOK));
+                       return TRUE;
+               }
+               case WM_CLOSE:
+               {
+                       EndDialog(hwndDlg, IDCANCEL);
+                       return TRUE;
+               }
+       }
+
+       return FALSE;
 }
-#endif
 
-int STDCALL
-WinMain(HINSTANCE hInstance,
-        HINSTANCE hPrevInstance,
-        LPSTR lpCmdLine,
-        int nShowCmd)
+int WINAPI
+WinMain(
+       IN HINSTANCE hInstance,
+       IN HINSTANCE hPrevInstance,
+       IN LPSTR lpCmdLine,
+       IN int nShowCmd)
 {
-#if SUPPORT_CONSOLESTART
-//  WCHAR LoginName[255];
-//  WCHAR Password[255];
-#endif
 #if 0
-  LSA_STRING ProcessName, PackageName;
-  HANDLE LsaHandle;
-  LSA_OPERATIONAL_MODE Mode;
-  ULONG AuthenticationPackage;
+       LSA_STRING ProcessName, PackageName;
+       HANDLE LsaHandle;
+       LSA_OPERATIONAL_MODE Mode;
+       BOOLEAN Old;
+       ULONG AuthenticationPackage;
+       NTSTATUS Status;
 #endif
+       ULONG HardErrorResponse;
+       MSG Msg;
+       HANDLE hThread;
+
+       UNREFERENCED_PARAMETER(hPrevInstance);
+       UNREFERENCED_PARAMETER(lpCmdLine);
+       UNREFERENCED_PARAMETER(nShowCmd);
+
+       hAppInstance = hInstance;
+
+       if (!RegisterLogonProcess(GetCurrentProcessId(), TRUE))
+       {
+               ERR("WL: Could not register logon process\n");
+               HandleShutdown(NULL, WLX_SAS_ACTION_SHUTDOWN_POWER_OFF);
+               NtShutdownSystem(ShutdownNoReboot);
+               ExitProcess(0);
+       }
+
+       WLSession = (PWLSESSION)HeapAlloc(GetProcessHeap(), 0, sizeof(WLSESSION));
+       if (!WLSession)
+       {
+               ERR("WL: Could not allocate memory for winlogon instance\n");
+               NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse);
+               ExitProcess(1);
+       }
+       ZeroMemory(WLSession, sizeof(WLSESSION));
+       WLSession->DialogTimeout = 120; /* 2 minutes */
+
+       if (!CreateWindowStationAndDesktops(WLSession))
+       {
+               ERR("WL: Could not create window station and desktops\n");
+               NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse);
+               ExitProcess(1);
+       }
+       LockWorkstation(WLSession);
+
+       if (!StartServicesManager())
+       {
+               ERR("WL: Could not start services.exe\n");
+               NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse);
+               ExitProcess(1);
+       }
 
-  hAppInstance = hInstance;
-
-  if(!RegisterLogonProcess(GetCurrentProcessId(), TRUE))
-  {
-    DbgPrint("WL: Could not register logon process\n");
-    NtShutdownSystem(ShutdownNoReboot);
-    ExitProcess(0);
-    return 0;
-  }
-
-#if START_LSASS
-   if (StartProcess(L"StartLsass"))
-     {
        if (!StartLsass())
-         {
-            DbgPrint("WL: Failed to start LSASS (0x%X)\n", GetLastError());
-         }
-     }
-#endif
-
-  if(!(WLSession = MsGinaInit()))
-  {
-    DbgPrint("WL: Failed to initialize msgina.dll\n");
-    NtShutdownSystem(ShutdownNoReboot);
-    ExitProcess(0);
-    return 0;
-  }
-
-  WLSession->LogonStatus = LOGON_INITIALIZING;
-
-  if(!WlxCreateWindowStationAndDesktops(WLSession))
-  {
-    NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, 0, 0, 0);
-    ExitProcess(1);
-    return 1;
-  }
-
-  /*
-   * Switch to winlogon desktop
-   */
-  /* FIXME: Do start up in the application desktop for now. */
-  SetThreadDesktop(WLSession->ApplicationDesktop);
-  if(!SwitchDesktop(WLSession->ApplicationDesktop))
-  {
-    DbgPrint("WL: Cannot switch to Winlogon desktop (0x%X)\n", GetLastError());
-  }
-
-  InitServices();
-  
-  /* Check for pending setup */
-  if (GetSetupType () != 0)
-  {
-    DPRINT ("Winlogon: CheckForSetup() in setup mode\n");
-
-    /* Run setup and reboot when done */
-    RunSetup();
-
-    NtShutdownSystem(ShutdownReboot);
-    ExitProcess(0);
-    return 0;
-  }
-
-#if SUPPORT_CONSOLESTART
- StartConsole = !StartIntoGUI();
-#endif
- if(!InitializeSAS(WLSession))
-  {
-    DbgPrint("WL: Failed to initialize SAS\n");
-    ExitProcess(2);
-    return 2;
-  }
+       {
+               ERR("WL: Failed to start lsass.exe service (error %lu)\n", GetLastError());
+               NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, 0, OptionOk, &HardErrorResponse);
+               ExitProcess(1);
+       }
+
+       /* Load and initialize gina */
+       if (!GinaInit(WLSession))
+       {
+               ERR("WL: Failed to initialize Gina\n");
+               DialogBoxParam(hAppInstance, MAKEINTRESOURCE(IDD_GINALOADFAILED), GetDesktopWindow(), GinaLoadFailedWindowProc, (LPARAM)L"");
+               HandleShutdown(WLSession, WLX_SAS_ACTION_SHUTDOWN_REBOOT);
+               ExitProcess(1);
+       }
+
+       DisplayStatusMessage(WLSession, WLSession->WinlogonDesktop, IDS_REACTOSISSTARTINGUP);
 
 #if 0
-   /* real winlogon uses "Winlogon" */
-   RtlInitUnicodeString((PUNICODE_STRING)&ProcessName, L"Winlogon");
-   Status = LsaRegisterLogonProcess(&ProcessName, &LsaHandle, &Mode);
-   if (!NT_SUCCESS(Status))
-   {
-     switch(Status)
-     {
-       case STATUS_PORT_CONNECTION_REFUSED:
-         /* FIXME - we don't have the 'SeTcbPrivilege' pivilege, so set it or call
-                    LsaAddAccountRights() and try again */
-         DbgPrint("WL: LsaRegisterLogonProcess() returned STATUS_PORT_CONNECTION_REFUSED\n");
-         break;
-       case STATUS_NAME_TOO_LONG:
-         DbgPrint("WL: LsaRegisterLogonProcess() returned STATUS_NAME_TOO_LONG\n");
-         break;
-       default:
-         DbgPrint("WL: Failed to connect to LSASS\n");
-         break;
-     }
-     return(1);
-   }
-
-   RtlInitUnicodeString((PUNICODE_STRING)&PackageName, L"Kerberos");
-   Status = LsaLookupAuthenticationPackage(LsaHandle, &PackageName, &AuthenticationPackage);
-   if (!NT_SUCCESS(Status))
-   {
-     LsaDeregisterLogonProcess(LsaHandle);
-     DbgPrint("WL: Failed to lookup authentication package\n");
-     return(1);
-   }
+       /* Connect to NetLogon service (lsass.exe) */
+       /* Real winlogon uses "Winlogon" */
+       RtlInitUnicodeString((PUNICODE_STRING)&ProcessName, L"Winlogon");
+       Status = LsaRegisterLogonProcess(&ProcessName, &LsaHandle, &Mode);
+       if (Status == STATUS_PORT_CONNECTION_REFUSED)
+       {
+               /* Add the 'SeTcbPrivilege' privilege and try again */
+               Status = RtlAdjustPrivilege(SE_TCB_PRIVILEGE, TRUE, TRUE, &Old);
+               if (!NT_SUCCESS(Status))
+               {
+                       ERR("RtlAdjustPrivilege() failed with error %lu\n", LsaNtStatusToWinError(Status));
+                       return 1;
+               }
+               Status = LsaRegisterLogonProcess(&ProcessName, &LsaHandle, &Mode);
+       }
+       if (!NT_SUCCESS(Status))
+       {
+               ERR("LsaRegisterLogonProcess() failed with error %lu\n", LsaNtStatusToWinError(Status));
+               return 1;
+       }
+
+       RtlInitUnicodeString((PUNICODE_STRING)&PackageName, MICROSOFT_KERBEROS_NAME_W);
+       Status = LsaLookupAuthenticationPackage(LsaHandle, &PackageName, &AuthenticationPackage);
+       if (!NT_SUCCESS(Status))
+       {
+               ERR("LsaLookupAuthenticationPackage() failed with error %lu\n", LsaNtStatusToWinError(Status));
+               LsaDeregisterLogonProcess(LsaHandle);
+               return 1;
+       }
 #endif
 
-   /* FIXME: Create a window class and associate a Winlogon
-    *        window procedure with it.
-    *        Register SAS with the window.
-    *        Register for logoff notification
-    */
-
-   /* Main loop */
-#if 0
-   /* Display login prompt */
-   WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),
-                LoginPrompt,
-                strlen(LoginPrompt),  // wcslen(LoginPrompt),
-                &Result,
-                NULL);
-   i = 0;
-   do
-     {
-       ReadConsole(GetStdHandle(STD_INPUT_HANDLE),
-                   &LoginName[i],
-                   1,
-                   &Result,
-                   NULL);
-       i++;
-     } while (LoginName[i - 1] != '\n');
-   LoginName[i - 1] = 0;
-
-   /* Display password prompt */
-   WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),
-                PasswordPrompt,
-                strlen(PasswordPrompt),  // wcslen(PasswordPrompt),
-                &Result,
-                NULL);
-   i = 0;
-   do
-     {
-       ReadConsole(GetStdHandle(STD_INPUT_HANDLE),
-                   &Password[i],
-                   1,
-                   &Result,
-                   NULL);
-       i++;
-     } while (Password[i - 1] != '\n');
-   Password[i - 1] =0;
-#endif
-
-#if SUPPORT_CONSOLESTART
- if(StartConsole)
- {
-//   if (! DoLogonUser(LoginName, Password))
-   if (! DoLogonUser(L"Administrator", L"Secret"))
-     {
-     }
-
-   NtShutdownSystem(ShutdownNoReboot);
-   ExitProcess(0);
- }
- else
- {
-#endif
-
-   RegisterHotKeys();
-
-   SessionLoop(WLSession);
-
-   UnregisterHotKeys();
-
-   /* FIXME - Flush disks and registry, ... */
-
-   if(WLSession->LogonStatus == LOGON_SHUTDOWN)
-   {
-     /* FIXME - only show this dialog if it's a shutdown and the computer doesn't support APM */
-     switch(DialogBox(hInstance, MAKEINTRESOURCE(IDD_SHUTDOWNCOMPUTER), 0, ShutdownComputerProc))
-     {
-       case IDC_BTNSHTDOWNCOMPUTER:
-         NtShutdownSystem(ShutdownReboot);
-         break;
-       default:
-         NtShutdownSystem(ShutdownNoReboot);
-         break;
-     }
-     ExitProcess(0);
-   }
-   else
-   {
-     DbgPrint("WL: LogonStatus != LOGON_SHUTDOWN!!!\n");
-     ExitProcess(0);
-   }
-#if SUPPORT_CONSOLESTART
- }
-#endif
-
-   return 0;
-}
-
-BOOL
-DisplayStatusMessage(PWLSESSION Session, HDESK hDesktop, DWORD dwOptions, PWSTR pTitle, PWSTR pMessage)
-{
-  if(Session->SuppressStatus)
-  {
-    return TRUE;
-  }
-
-  #if SUPPORT_CONSOLESTART
-  if(StartConsole)
-  {
-    if(pMessage)
-    {
-      DbgPrint("WL-Status: %ws\n", pMessage);
-    }
-    return TRUE;
-  }
-  #endif
-
-  return Session->MsGina.Functions.WlxDisplayStatusMessage(Session->MsGina.Context, hDesktop, dwOptions, pTitle, pMessage);
-}
-
-BOOL
-InitServices(void)
-{
-  WCHAR StatusMsg[256];
-
-  LoadString(hAppInstance, IDS_REACTOSISSTARTINGUP, StatusMsg, 256 * sizeof(WCHAR));
-  DisplayStatusMessage(WLSession, WLSession->ApplicationDesktop, 0, NULL, StatusMsg);
-
-  /* start system processes (services.exe & lsass.exe) */
-  if(StartProcess(L"StartServices"))
-  {
-       if(!StartServices())
-    {
-      DbgPrint("WL: Failed to start Services (0x%X)\n", GetLastError());
-    }
-  }
-
-  return TRUE;
+       /* Create a hidden window to get SAS notifications */
+       if (!InitializeSAS(WLSession))
+       {
+               ERR("WL: Failed to initialize SAS\n");
+               ExitProcess(2);
+       }
+
+       //DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_PREPARENETWORKCONNECTIONS);
+       //DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_APPLYINGCOMPUTERSETTINGS);
+
+       /* Display logged out screen */
+       WLSession->LogonStatus = WKSTA_IS_LOGGED_OFF;
+       RemoveStatusMessage(WLSession);
+
+       /* Check for pending setup */
+       if (GetSetupType() != 0)
+       {
+               TRACE("WL: Setup mode detected\n");
+
+               /* Run setup and reboot when done */
+               SwitchDesktop(WLSession->ApplicationDesktop);
+               RunSetup();
+       }
+       else
+               PostMessageW(WLSession->SASWindow, WLX_WM_SAS, WLX_SAS_TYPE_TIMEOUT, 0);
+
+       /* Play logon sound */
+       hThread = CreateThread(NULL, 0, PlayLogonSoundThread, NULL, 0, NULL);
+       if (hThread)
+       {
+               CloseHandle(hThread);
+       }
+
+       /* Tell kernel that CurrentControlSet is good (needed
+        * to support Last good known configuration boot) */
+       NtInitializeRegistry(CM_BOOT_FLAG_ACCEPTED | 1);
+
+       /* Message loop for the SAS window */
+       while (GetMessageW(&Msg, WLSession->SASWindow, 0, 0))
+       {
+               TranslateMessage(&Msg);
+               DispatchMessageW(&Msg);
+       }
+
+       /* We never go there */
+
+       return 0;
 }
-
-DWORD
-DoLogin(PWLSESSION Session)
-{
-  DWORD WlxAction, Options;
-  WLX_MPR_NOTIFY_INFO MprNotifyInfo;
-  PWLX_PROFILE_V2_0 Profile;
-  PSID LogonSid = NULL;
-  HANDLE Token;
-
-  /* FIXME - Create a Logon Sid
-  if(!(LogonSid = CreateUserLogonSid(NULL)))
-  {
-    return WLX_SAS_ACTION_NONE;
-  }
-  */
-
-  Options = 0;
-  WlxAction = Session->MsGina.Functions.WlxLoggedOutSAS(Session->MsGina.Context,
-                                                        Session->SASAction,
-                                                        &Session->LogonId,
-                                                        LogonSid,
-                                                        &Options,
-                                                        &Token,
-                                                        &MprNotifyInfo,
-                                                        (PVOID*)&Profile);
-
-  return WlxAction;
-}
-
-void
-SessionLoop(PWLSESSION Session)
-{
-  //WCHAR StatusMsg[256];
- // HANDLE hShutdownEvent;
-  DWORD WlxAction;
-  MSG Msg;
-
-  WlxAction = WLX_SAS_ACTION_NONE;
-  Session->LogonStatus = LOGON_NONE;
-  while(WlxAction == WLX_SAS_ACTION_NONE)
-  {
-    RemoveStatusMessage(Session);
-    if(Session->LogonStatus == LOGON_NONE)
-    {
-      Session->LogonStatus = LOGON_SHOWINGLOGON;
-      /* we're ready to display a logon window,
-         don't timeout dialogboxes here */
-      WlxSetTimeout(Session->MsGina.Context, 0);
-      Session->SuppressStatus = TRUE;
-      /* tell msgina to show a window telling the user one can logon */
-      #if SUPPORT_CONSOLESTART
-      if(!StartConsole)
-      #endif
-      DisplaySASNotice(Session);
-      Session->SuppressStatus = FALSE;
-
-      if(Session->SASAction == WLX_SAS_ACTION_LOGOFF)
-      {
-        /* the system wants to log off here */
-        Session->LogonStatus = LOGON_SHUTDOWN;
-        break;
-      }
-    }
-
-    WlxAction = DoLogin(Session);
-    if(WlxAction == WLX_SAS_ACTION_LOGOFF)
-    {
-      /* the user doesn't want to login, instead pressed cancel
-         we should display the window again so one can logon again */
-      /* FIXME - disconnect any connections in case we did a remote logon */
-      DbgPrint("WL: DoLogin failed\n");
-      WlxAction = WLX_SAS_ACTION_NONE;
-    }
-    if(WlxAction == WLX_SAS_ACTION_NONE)
-    {
-      if(Session->SASAction == WLX_SAS_ACTION_LOGOFF)
-      {
-        /* system is about to shut down, leave the main loop */
-        Session->LogonStatus = LOGON_SHUTDOWN;
-        break;
-      }
-      Session->LogonStatus = LOGON_NONE;
-      continue;
-    }
-
-    /* FIXME - don't leave the loop when suspending the computer */
-    if(WLX_SUSPENDING(WlxAction))
-    {
-      Session->LogonStatus = LOGON_NONE;
-      WlxAction = WLX_SAS_ACTION_NONE;
-      /* don't leave the loop */
-      continue;
-    }
-
-    if(WLX_SHUTTINGDOWN(WlxAction))
-    {
-      Session->LogonStatus = LOGON_SHUTDOWN;
-      /* leave the loop here */
-      break;
-    }
-
-    /* Message loop for the SAS window */
-    while(GetMessage(&Msg, 0, 0, 0))
-    {
-      if (Msg.message == WM_HOTKEY)
-        HandleHotKey(&Msg);
-      TranslateMessage(&Msg);
-      DispatchMessage(&Msg);
-    }
-  }
-   /*
-   LoadString(hAppInstance, IDS_PREPARENETWORKCONNECTIONS, StatusMsg, 256 * sizeof(WCHAR));
-   MsGinaInst->Functions->WlxDisplayStatusMessage(MsGinaInst->Context,
-                                                  ApplicationDesktop,
-                                                  0,
-                                                  NULL,
-                                                  StatusMsg);
-
-
-   Sleep(150);
-
-   LoadString(hAppInstance, IDS_APPLYINGCOMPUTERSETTINGS, StatusMsg, 256 * sizeof(WCHAR));
-   MsGinaInst->Functions->WlxDisplayStatusMessage(MsGinaInst->Context,
-                                                  ApplicationDesktop,
-                                                  0,
-                                                  NULL,
-                                                  StatusMsg);
-
-
-   Sleep(150);
-
-   MsGinaInst->Functions->WlxRemoveStatusMessage(MsGinaInst->Context);
-   MsGinaInst->Functions->WlxRemoveStatusMessage(MsGinaInst->Context);
-   MsGinaInst->Functions->WlxRemoveStatusMessage(MsGinaInst->Context);
-
-
-    Sleep(250);
-
-   LoadString(hAppInstance, IDS_LOADINGYOURPERSONALSETTINGS, StatusMsg, 256 * sizeof(WCHAR));
-   MsGinaInst->Functions->WlxDisplayStatusMessage(MsGinaInst->Context,
-                                                  ApplicationDesktop,
-                                                  0,
-                                                  NULL,
-                                                  StatusMsg);
-
-   Sleep(150);
-
-   LoadString(hAppInstance, IDS_APPLYINGYOURPERSONALSETTINGS, StatusMsg, 256 * sizeof(WCHAR));
-   MsGinaInst->Functions->WlxDisplayStatusMessage(MsGinaInst->Context,
-                                                  ApplicationDesktop,
-                                                  0,
-                                                  NULL,
-                                                  StatusMsg);
-
-
-   Sleep(150);
-
-   MsGinaInst->Functions->WlxRemoveStatusMessage(MsGinaInst->Context);
-   MsGinaInst->Functions->WlxRemoveStatusMessage(MsGinaInst->Context);
-
-   if(!MsGinaInst->Functions->WlxActivateUserShell(MsGinaInst->Context,
-                                                   L"WinSta0\\Default",
-                                                   NULL,
-                                                   NULL))
-   {
-     LoadString(hAppInstance, IDS_FAILEDACTIVATEUSERSHELL, StatusMsg, 256 * sizeof(WCHAR));
-     MessageBox(0, StatusMsg, NULL, MB_ICONERROR);
-     SetEvent(hShutdownEvent);
-   }
-
-
-   WaitForSingleObject(hShutdownEvent, INFINITE);
-   CloseHandle(hShutdownEvent);
-
-   LoadString(hAppInstance, IDS_SAVEYOURSETTINGS, StatusMsg, 256 * sizeof(WCHAR));
-   MsGinaInst->Functions->WlxDisplayStatusMessage(MsGinaInst->Context,
-                                                  ApplicationDesktop,
-                                                  0,
-                                                  NULL,
-                                                  StatusMsg);
-
-
-   Sleep(150);
-
-   MsGinaInst->Functions->WlxShutdown(MsGinaInst->Context, WLX_SAS_ACTION_SHUTDOWN);
-
-   LoadString(hAppInstance, IDS_REACTOSISSHUTTINGDOWN, StatusMsg, 256 * sizeof(WCHAR));
-   MsGinaInst->Functions->WlxDisplayStatusMessage(MsGinaInst->Context,
-                                                  ApplicationDesktop,
-                                                  0,
-                                                  NULL,
-                                                  StatusMsg);
-
-
-   Sleep(250);
-
-   MsGinaInst->Functions->WlxRemoveStatusMessage(MsGinaInst->Context);
-   MsGinaInst->Functions->WlxRemoveStatusMessage(MsGinaInst->Context);
-   */
-}
-