set most of trunk svn property eol-style:native
[reactos.git] / reactos / dll / win32 / msgina / gui.c
index 61ac860..be6e259 100644 (file)
-/*\r
- * PROJECT:         ReactOS msgina.dll\r
- * FILE:            dll/win32/msgina/gui.c\r
- * PURPOSE:         ReactOS Logon GINA DLL\r
- * PROGRAMMER:      HervĂ© Poussineau (hpoussin@reactos.org)\r
- */\r
-\r
-#include "msgina.h"\r
-\r
-//#define YDEBUG\r
-#include <wine/debug.h>\r
-\r
-typedef struct _DISPLAYSTATUSMSG\r
-{\r
-       PGINA_CONTEXT Context;\r
-       HDESK hDesktop;\r
-       DWORD dwOptions;\r
-       PWSTR pTitle;\r
-       PWSTR pMessage;\r
-       HANDLE StartupEvent;\r
-} DISPLAYSTATUSMSG, *PDISPLAYSTATUSMSG;\r
-\r
-static BOOL\r
-GUIInitialize(\r
-       IN OUT PGINA_CONTEXT pgContext)\r
-{\r
-       TRACE("GUIInitialize(%p)\n", pgContext);\r
-       return TRUE;\r
-}\r
-\r
-static BOOL CALLBACK\r
-StatusMessageWindowProc(\r
-       IN HWND hwndDlg,\r
-       IN UINT uMsg,\r
-       IN WPARAM wParam,\r
-       IN LPARAM lParam)\r
-{\r
-       switch (uMsg)\r
-       {\r
-               case WM_INITDIALOG:\r
-               {\r
-                       PDISPLAYSTATUSMSG msg = (PDISPLAYSTATUSMSG)lParam;\r
-                       if (!msg)\r
-                               return FALSE;\r
-\r
-                       msg->Context->hStatusWindow = hwndDlg;\r
-\r
-                       if (msg->pTitle)\r
-                               SetWindowTextW(hwndDlg, msg->pTitle);\r
-                       SetDlgItemTextW(hwndDlg, IDC_STATUSLABEL, msg->pMessage);\r
-                       if (!msg->Context->SignaledStatusWindowCreated)\r
-                       {\r
-                               msg->Context->SignaledStatusWindowCreated = TRUE;\r
-                               SetEvent(msg->StartupEvent);\r
-                       }\r
-                       return TRUE;\r
-               }\r
-       }\r
-       return FALSE;\r
-}\r
-\r
-static DWORD WINAPI\r
-StartupWindowThread(LPVOID lpParam)\r
-{\r
-       HDESK OldDesk;\r
-       PDISPLAYSTATUSMSG msg = (PDISPLAYSTATUSMSG)lpParam;\r
-\r
-       OldDesk = GetThreadDesktop(GetCurrentThreadId());\r
-\r
-       if(!SetThreadDesktop(msg->hDesktop))\r
-       {\r
-               HeapFree(GetProcessHeap(), 0, lpParam);\r
-               return FALSE;\r
-       }\r
-       DialogBoxParam(\r
-               hDllInstance, \r
-               MAKEINTRESOURCE(IDD_STATUSWINDOW_DLG),\r
-               0,\r
-               StatusMessageWindowProc,\r
-               (LPARAM)lpParam);\r
-       SetThreadDesktop(OldDesk);\r
-\r
-       msg->Context->hStatusWindow = 0;\r
-       msg->Context->SignaledStatusWindowCreated = FALSE;\r
-\r
-       HeapFree(GetProcessHeap(), 0, lpParam);\r
-       return TRUE;\r
-}\r
-\r
-static BOOL\r
-GUIDisplayStatusMessage(\r
-       IN PGINA_CONTEXT pgContext,\r
-       IN HDESK hDesktop,\r
-       IN DWORD dwOptions,\r
-       IN PWSTR pTitle,\r
-       IN PWSTR pMessage)\r
-{\r
-       PDISPLAYSTATUSMSG msg;\r
-       HANDLE Thread;\r
-       DWORD ThreadId;\r
-\r
-       TRACE("GUIDisplayStatusMessage(%ws)\n", pMessage);\r
-\r
-       if (!pgContext->hStatusWindow)\r
-       {\r
-               msg = (PDISPLAYSTATUSMSG)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DISPLAYSTATUSMSG));\r
-               if(!msg)\r
-                       return FALSE;\r
-\r
-               msg->Context = pgContext;\r
-               msg->dwOptions = dwOptions;\r
-               msg->pTitle = pTitle;\r
-               msg->pMessage = pMessage;\r
-               msg->hDesktop = hDesktop;\r
-\r
-               msg->StartupEvent = CreateEvent(\r
-                       NULL,\r
-                       TRUE,\r
-                       FALSE,\r
-                       NULL);\r
-\r
-               if (!msg->StartupEvent)\r
-                       return FALSE;\r
-\r
-               Thread = CreateThread(\r
-                       NULL,\r
-                       0,\r
-                       StartupWindowThread,\r
-                       (PVOID)msg,\r
-                       0,\r
-                       &ThreadId);\r
-               if (Thread)\r
-               {\r
-                       CloseHandle(Thread);\r
-                       WaitForSingleObject(msg->StartupEvent, INFINITE);\r
-                       CloseHandle(msg->StartupEvent);\r
-                       return TRUE;\r
-               }\r
-\r
-               return FALSE;\r
-       }\r
-\r
-       if(pTitle)\r
-               SetWindowTextW(pgContext->hStatusWindow, pTitle);\r
-\r
-       SetDlgItemTextW(pgContext->hStatusWindow, IDC_STATUSLABEL, pMessage);\r
-\r
-       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 VOID\r
-GUIDisplaySASNotice(\r
-       IN OUT PGINA_CONTEXT pgContext)\r
-{\r
-       INT result;\r
-\r
-       TRACE("GUIDisplaySASNotice()\n");\r
-\r
-       /* Display the notice window */\r
-       result = DialogBoxParam(\r
-               pgContext->hDllInstance,\r
-               MAKEINTRESOURCE(IDD_NOTICE_DLG),\r
-               NULL,\r
-               NULL,\r
-               (LPARAM)NULL);\r
-       if (result == -1)\r
-       {\r
-               /* Failed to display the window. Do as if the user\r
-                * already has pressed CTRL+ALT+DELETE */\r
-               pgContext->pWlxFuncs->WlxSasNotify(pgContext->hWlx, WLX_SAS_TYPE_CTRL_ALT_DEL);\r
-       }\r
-}\r
-\r
-/* Get the text contained in a textbox. Allocates memory in pText\r
- * to contain the text. Returns TRUE in case of success */\r
-static BOOL\r
-GetTextboxText(\r
-       IN HWND hwndDlg,\r
-       IN INT TextboxId,\r
-       OUT LPWSTR *pText)\r
-{\r
-       LPWSTR Text;\r
-       int Count;\r
-\r
-       Count = GetWindowTextLength(GetDlgItem(hwndDlg, TextboxId));\r
-       Text = HeapAlloc(GetProcessHeap(), 0, (Count + 1) * sizeof(WCHAR));\r
-       if (!Text)\r
-               return FALSE;\r
-       if (Count != GetWindowTextW(GetDlgItem(hwndDlg, TextboxId), Text, Count + 1))\r
-       {\r
-               HeapFree(GetProcessHeap(), 0, Text);\r
-               return FALSE;\r
-       }\r
-       *pText = Text;\r
-       return TRUE;\r
-}\r
-\r
-static INT_PTR CALLBACK\r
-LoggedOnWindowProc(\r
-       IN HWND hwndDlg,\r
-       IN UINT uMsg,\r
-       IN WPARAM wParam,\r
-       IN LPARAM lParam)\r
-{\r
-       switch (uMsg)\r
-       {\r
-               case WM_COMMAND:\r
-               {\r
-                       switch (LOWORD(wParam))\r
-                       {\r
-                               case IDC_LOCK:\r
-                                       EndDialog(hwndDlg, WLX_SAS_ACTION_LOCK_WKSTA);\r
-                                       return TRUE;\r
-                               case IDC_LOGOFF:\r
-                                       EndDialog(hwndDlg, WLX_SAS_ACTION_LOGOFF);\r
-                                       return TRUE;\r
-                               case IDC_SHUTDOWN:\r
-                                       EndDialog(hwndDlg, WLX_SAS_ACTION_SHUTDOWN_POWER_OFF);\r
-                                       return TRUE;\r
-                               case IDC_TASKMGR:\r
-                                       EndDialog(hwndDlg, WLX_SAS_ACTION_TASKLIST);\r
-                                       return TRUE;\r
-                               case IDCANCEL:\r
-                                       EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);\r
-                                       return TRUE;\r
-                       }\r
-                       break;\r
-               }\r
-               case WM_INITDIALOG:\r
-               {\r
-                       SetFocus(GetDlgItem(hwndDlg, IDNO));\r
-                       return TRUE;\r
-               }\r
-               case WM_CLOSE:\r
-               {\r
-                       EndDialog(hwndDlg, IDNO);\r
-                       return TRUE;\r
-               }\r
-       }\r
-\r
-       return FALSE;\r
-}\r
-\r
-static INT\r
-GUILoggedOnSAS(\r
-       IN OUT PGINA_CONTEXT pgContext,\r
-       IN DWORD dwSasType)\r
-{\r
-       INT result;\r
-\r
-       TRACE("GUILoggedOnSAS()\n");\r
-\r
-       if (dwSasType != WLX_SAS_TYPE_CTRL_ALT_DEL)\r
-       {\r
-               /* Nothing to do for WLX_SAS_TYPE_TIMEOUT ; the dialog will\r
-                * close itself thanks to the use of WlxDialogBoxParam */\r
-               return WLX_SAS_ACTION_NONE;\r
-       }\r
-\r
-       result = pgContext->pWlxFuncs->WlxDialogBoxParam(\r
-               pgContext->hWlx,\r
-               pgContext->hDllInstance,\r
-               MAKEINTRESOURCEW(IDD_LOGGEDON_DLG),\r
-               NULL,\r
-               LoggedOnWindowProc,\r
-               (LPARAM)pgContext);\r
-       if (result >= WLX_SAS_ACTION_LOGON &&\r
-           result <= WLX_SAS_ACTION_SWITCH_CONSOLE)\r
-       {\r
-               return result;\r
-       }\r
-       return WLX_SAS_ACTION_NONE;\r
-}\r
-\r
-static INT_PTR CALLBACK\r
-LoggedOutWindowProc(\r
-       IN HWND hwndDlg,\r
-       IN UINT uMsg,\r
-       IN WPARAM wParam,\r
-       IN LPARAM lParam)\r
-{\r
-       PGINA_CONTEXT pgContext;\r
-\r
-       pgContext = (PGINA_CONTEXT)GetWindowLongPtr(hwndDlg, GWL_USERDATA);\r
-\r
-       switch (uMsg)\r
-       {\r
-               case WM_INITDIALOG:\r
-               {\r
-                       /* FIXME: take care of DontDisplayLastUserName, NoDomainUI, ShutdownWithoutLogon */\r
-                       pgContext = (PGINA_CONTEXT)lParam;\r
-                       SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)pgContext);\r
-                       SetFocus(GetDlgItem(hwndDlg, IDC_USERNAME));\r
-\r
-                       pgContext->hBitmap = LoadImage(hDllInstance, MAKEINTRESOURCE(IDI_ROSLOGO), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);\r
-                       return TRUE;\r
-               }\r
-               case WM_PAINT:\r
-               {\r
-                       PAINTSTRUCT ps;\r
-                       HDC hdc;\r
-                       if (pgContext->hBitmap)\r
-                       {\r
-                               hdc = BeginPaint(hwndDlg, &ps);\r
-                               DrawState(hdc, NULL, NULL, (LPARAM)pgContext->hBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);\r
-                               EndPaint(hwndDlg, &ps);\r
-                       }\r
-                       return TRUE;\r
-               }\r
-               case WM_DESTROY:\r
-               {\r
-                       DeleteObject(pgContext->hBitmap);\r
-                       return TRUE;\r
-               }\r
-               case WM_COMMAND:\r
-               {\r
-                       switch (LOWORD(wParam))\r
-                       {\r
-                               case IDOK:\r
-                               {\r
-                                       LPWSTR UserName = NULL, Password = NULL;\r
-                                       INT result = WLX_SAS_ACTION_NONE;\r
-\r
-                                       if (GetTextboxText(hwndDlg, IDC_USERNAME, &UserName) && *UserName == '\0')\r
-                                               break;\r
-                                       if (GetTextboxText(hwndDlg, IDC_PASSWORD, &Password) &&\r
-                                           DoLoginTasks(pgContext, UserName, NULL, Password))\r
-                                       {\r
-                                               result = WLX_SAS_ACTION_LOGON;\r
-                                       }\r
-                                       HeapFree(GetProcessHeap(), 0, UserName);\r
-                                       HeapFree(GetProcessHeap(), 0, Password);\r
-                                       EndDialog(hwndDlg, result);\r
-                                       return TRUE;\r
-                               }\r
-                               case IDCANCEL:\r
-                               {\r
-                                       EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);\r
-                                       return TRUE;\r
-                               }\r
-                               case IDC_SHUTDOWN:\r
-                               {\r
-                                       EndDialog(hwndDlg, WLX_SAS_ACTION_SHUTDOWN);\r
-                                       return TRUE;\r
-                               }\r
-                       }\r
-                       break;\r
-               }\r
-       }\r
-\r
-       return FALSE;\r
-}\r
-\r
-static INT\r
-GUILoggedOutSAS(\r
-       IN OUT PGINA_CONTEXT pgContext)\r
-{\r
-       int result;\r
-\r
-       TRACE("GUILoggedOutSAS()\n");\r
-\r
-       result = pgContext->pWlxFuncs->WlxDialogBoxParam(\r
-               pgContext->hWlx,\r
-               pgContext->hDllInstance,\r
-               MAKEINTRESOURCEW(IDD_LOGGEDOUT_DLG),\r
-               NULL,\r
-               LoggedOutWindowProc,\r
-               (LPARAM)pgContext);\r
-       if (result >= WLX_SAS_ACTION_LOGON &&\r
-           result <= WLX_SAS_ACTION_SWITCH_CONSOLE)\r
-       {\r
-               WARN("WlxLoggedOutSAS() returns 0x%x\n", result);\r
-               return result;\r
-       }\r
-\r
-       WARN("WlxDialogBoxParam() failed (0x%x)\n", result);\r
-       return WLX_SAS_ACTION_NONE;\r
-}\r
-\r
-static INT\r
-GUILockedSAS(\r
-       IN OUT PGINA_CONTEXT pgContext)\r
-{\r
-       TRACE("GUILockedSAS()\n");\r
-\r
-       UNIMPLEMENTED;\r
-       return WLX_SAS_ACTION_UNLOCK_WKSTA;\r
-}\r
-\r
-GINA_UI GinaGraphicalUI = {\r
-       GUIInitialize,\r
-       GUIDisplayStatusMessage,\r
-       GUIRemoveStatusMessage,\r
-       GUIDisplaySASNotice,\r
-       GUILoggedOnSAS,\r
-       GUILoggedOutSAS,\r
-       GUILockedSAS,\r
-};\r
+/*
+ * PROJECT:         ReactOS msgina.dll
+ * FILE:            dll/win32/msgina/gui.c
+ * PURPOSE:         ReactOS Logon GINA DLL
+ * PROGRAMMER:      HervĂ© Poussineau (hpoussin@reactos.org)
+ */
+
+#include "msgina.h"
+
+//#define YDEBUG
+#include <wine/debug.h>
+
+typedef struct _DISPLAYSTATUSMSG
+{
+       PGINA_CONTEXT Context;
+       HDESK hDesktop;
+       DWORD dwOptions;
+       PWSTR pTitle;
+       PWSTR pMessage;
+       HANDLE StartupEvent;
+} DISPLAYSTATUSMSG, *PDISPLAYSTATUSMSG;
+
+static BOOL
+GUIInitialize(
+       IN OUT PGINA_CONTEXT pgContext)
+{
+       TRACE("GUIInitialize(%p)\n", pgContext);
+       return TRUE;
+}
+
+static BOOL CALLBACK
+StatusMessageWindowProc(
+       IN HWND hwndDlg,
+       IN UINT uMsg,
+       IN WPARAM wParam,
+       IN LPARAM lParam)
+{
+       switch (uMsg)
+       {
+               case WM_INITDIALOG:
+               {
+                       PDISPLAYSTATUSMSG msg = (PDISPLAYSTATUSMSG)lParam;
+                       if (!msg)
+                               return FALSE;
+
+                       msg->Context->hStatusWindow = hwndDlg;
+
+                       if (msg->pTitle)
+                               SetWindowTextW(hwndDlg, msg->pTitle);
+                       SetDlgItemTextW(hwndDlg, IDC_STATUSLABEL, msg->pMessage);
+                       if (!msg->Context->SignaledStatusWindowCreated)
+                       {
+                               msg->Context->SignaledStatusWindowCreated = TRUE;
+                               SetEvent(msg->StartupEvent);
+                       }
+                       return TRUE;
+               }
+       }
+       return FALSE;
+}
+
+static DWORD WINAPI
+StartupWindowThread(LPVOID lpParam)
+{
+       HDESK OldDesk;
+       PDISPLAYSTATUSMSG msg = (PDISPLAYSTATUSMSG)lpParam;
+
+       OldDesk = GetThreadDesktop(GetCurrentThreadId());
+
+       if(!SetThreadDesktop(msg->hDesktop))
+       {
+               HeapFree(GetProcessHeap(), 0, lpParam);
+               return FALSE;
+       }
+       DialogBoxParam(
+               hDllInstance, 
+               MAKEINTRESOURCE(IDD_STATUSWINDOW_DLG),
+               0,
+               StatusMessageWindowProc,
+               (LPARAM)lpParam);
+       SetThreadDesktop(OldDesk);
+
+       msg->Context->hStatusWindow = 0;
+       msg->Context->SignaledStatusWindowCreated = FALSE;
+
+       HeapFree(GetProcessHeap(), 0, lpParam);
+       return TRUE;
+}
+
+static BOOL
+GUIDisplayStatusMessage(
+       IN PGINA_CONTEXT pgContext,
+       IN HDESK hDesktop,
+       IN DWORD dwOptions,
+       IN PWSTR pTitle,
+       IN PWSTR pMessage)
+{
+       PDISPLAYSTATUSMSG msg;
+       HANDLE Thread;
+       DWORD ThreadId;
+
+       TRACE("GUIDisplayStatusMessage(%ws)\n", pMessage);
+
+       if (!pgContext->hStatusWindow)
+       {
+               msg = (PDISPLAYSTATUSMSG)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DISPLAYSTATUSMSG));
+               if(!msg)
+                       return FALSE;
+
+               msg->Context = pgContext;
+               msg->dwOptions = dwOptions;
+               msg->pTitle = pTitle;
+               msg->pMessage = pMessage;
+               msg->hDesktop = hDesktop;
+
+               msg->StartupEvent = CreateEvent(
+                       NULL,
+                       TRUE,
+                       FALSE,
+                       NULL);
+
+               if (!msg->StartupEvent)
+                       return FALSE;
+
+               Thread = CreateThread(
+                       NULL,
+                       0,
+                       StartupWindowThread,
+                       (PVOID)msg,
+                       0,
+                       &ThreadId);
+               if (Thread)
+               {
+                       CloseHandle(Thread);
+                       WaitForSingleObject(msg->StartupEvent, INFINITE);
+                       CloseHandle(msg->StartupEvent);
+                       return TRUE;
+               }
+
+               return FALSE;
+       }
+
+       if(pTitle)
+               SetWindowTextW(pgContext->hStatusWindow, pTitle);
+
+       SetDlgItemTextW(pgContext->hStatusWindow, IDC_STATUSLABEL, pMessage);
+
+       return TRUE;
+}
+
+static BOOL
+GUIRemoveStatusMessage(
+       IN PGINA_CONTEXT pgContext)
+{
+       if (pgContext->hStatusWindow)
+       {
+               EndDialog(pgContext->hStatusWindow, 0);
+               pgContext->hStatusWindow = 0;
+       }
+
+       return TRUE;
+}
+
+static VOID
+GUIDisplaySASNotice(
+       IN OUT PGINA_CONTEXT pgContext)
+{
+       INT result;
+
+       TRACE("GUIDisplaySASNotice()\n");
+
+       /* Display the notice window */
+       result = DialogBoxParam(
+               pgContext->hDllInstance,
+               MAKEINTRESOURCE(IDD_NOTICE_DLG),
+               NULL,
+               NULL,
+               (LPARAM)NULL);
+       if (result == -1)
+       {
+               /* Failed to display the window. Do as if the user
+                * already has pressed CTRL+ALT+DELETE */
+               pgContext->pWlxFuncs->WlxSasNotify(pgContext->hWlx, WLX_SAS_TYPE_CTRL_ALT_DEL);
+       }
+}
+
+/* Get the text contained in a textbox. Allocates memory in pText
+ * to contain the text. Returns TRUE in case of success */
+static BOOL
+GetTextboxText(
+       IN HWND hwndDlg,
+       IN INT TextboxId,
+       OUT LPWSTR *pText)
+{
+       LPWSTR Text;
+       int Count;
+
+       Count = GetWindowTextLength(GetDlgItem(hwndDlg, TextboxId));
+       Text = HeapAlloc(GetProcessHeap(), 0, (Count + 1) * sizeof(WCHAR));
+       if (!Text)
+               return FALSE;
+       if (Count != GetWindowTextW(GetDlgItem(hwndDlg, TextboxId), Text, Count + 1))
+       {
+               HeapFree(GetProcessHeap(), 0, Text);
+               return FALSE;
+       }
+       *pText = Text;
+       return TRUE;
+}
+
+static INT_PTR CALLBACK
+LoggedOnWindowProc(
+       IN HWND hwndDlg,
+       IN UINT uMsg,
+       IN WPARAM wParam,
+       IN LPARAM lParam)
+{
+       switch (uMsg)
+       {
+               case WM_COMMAND:
+               {
+                       switch (LOWORD(wParam))
+                       {
+                               case IDC_LOCK:
+                                       EndDialog(hwndDlg, WLX_SAS_ACTION_LOCK_WKSTA);
+                                       return TRUE;
+                               case IDC_LOGOFF:
+                                       EndDialog(hwndDlg, WLX_SAS_ACTION_LOGOFF);
+                                       return TRUE;
+                               case IDC_SHUTDOWN:
+                                       EndDialog(hwndDlg, WLX_SAS_ACTION_SHUTDOWN_POWER_OFF);
+                                       return TRUE;
+                               case IDC_TASKMGR:
+                                       EndDialog(hwndDlg, WLX_SAS_ACTION_TASKLIST);
+                                       return TRUE;
+                               case IDCANCEL:
+                                       EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
+                                       return TRUE;
+                       }
+                       break;
+               }
+               case WM_INITDIALOG:
+               {
+                       SetFocus(GetDlgItem(hwndDlg, IDNO));
+                       return TRUE;
+               }
+               case WM_CLOSE:
+               {
+                       EndDialog(hwndDlg, IDNO);
+                       return TRUE;
+               }
+       }
+
+       return FALSE;
+}
+
+static INT
+GUILoggedOnSAS(
+       IN OUT PGINA_CONTEXT pgContext,
+       IN DWORD dwSasType)
+{
+       INT result;
+
+       TRACE("GUILoggedOnSAS()\n");
+
+       if (dwSasType != WLX_SAS_TYPE_CTRL_ALT_DEL)
+       {
+               /* Nothing to do for WLX_SAS_TYPE_TIMEOUT ; the dialog will
+                * close itself thanks to the use of WlxDialogBoxParam */
+               return WLX_SAS_ACTION_NONE;
+       }
+
+       result = pgContext->pWlxFuncs->WlxDialogBoxParam(
+               pgContext->hWlx,
+               pgContext->hDllInstance,
+               MAKEINTRESOURCEW(IDD_LOGGEDON_DLG),
+               NULL,
+               LoggedOnWindowProc,
+               (LPARAM)pgContext);
+       if (result >= WLX_SAS_ACTION_LOGON &&
+           result <= WLX_SAS_ACTION_SWITCH_CONSOLE)
+       {
+               return result;
+       }
+       return WLX_SAS_ACTION_NONE;
+}
+
+static INT_PTR CALLBACK
+LoggedOutWindowProc(
+       IN HWND hwndDlg,
+       IN UINT uMsg,
+       IN WPARAM wParam,
+       IN LPARAM lParam)
+{
+       PGINA_CONTEXT pgContext;
+
+       pgContext = (PGINA_CONTEXT)GetWindowLongPtr(hwndDlg, GWL_USERDATA);
+
+       switch (uMsg)
+       {
+               case WM_INITDIALOG:
+               {
+                       /* FIXME: take care of DontDisplayLastUserName, NoDomainUI, ShutdownWithoutLogon */
+                       pgContext = (PGINA_CONTEXT)lParam;
+                       SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)pgContext);
+                       SetFocus(GetDlgItem(hwndDlg, IDC_USERNAME));
+
+                       pgContext->hBitmap = LoadImage(hDllInstance, MAKEINTRESOURCE(IDI_ROSLOGO), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
+                       return TRUE;
+               }
+               case WM_PAINT:
+               {
+                       PAINTSTRUCT ps;
+                       HDC hdc;
+                       if (pgContext->hBitmap)
+                       {
+                               hdc = BeginPaint(hwndDlg, &ps);
+                               DrawState(hdc, NULL, NULL, (LPARAM)pgContext->hBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);
+                               EndPaint(hwndDlg, &ps);
+                       }
+                       return TRUE;
+               }
+               case WM_DESTROY:
+               {
+                       DeleteObject(pgContext->hBitmap);
+                       return TRUE;
+               }
+               case WM_COMMAND:
+               {
+                       switch (LOWORD(wParam))
+                       {
+                               case IDOK:
+                               {
+                                       LPWSTR UserName = NULL, Password = NULL;
+                                       INT result = WLX_SAS_ACTION_NONE;
+
+                                       if (GetTextboxText(hwndDlg, IDC_USERNAME, &UserName) && *UserName == '\0')
+                                               break;
+                                       if (GetTextboxText(hwndDlg, IDC_PASSWORD, &Password) &&
+                                           DoLoginTasks(pgContext, UserName, NULL, Password))
+                                       {
+                                               result = WLX_SAS_ACTION_LOGON;
+                                       }
+                                       HeapFree(GetProcessHeap(), 0, UserName);
+                                       HeapFree(GetProcessHeap(), 0, Password);
+                                       EndDialog(hwndDlg, result);
+                                       return TRUE;
+                               }
+                               case IDCANCEL:
+                               {
+                                       EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
+                                       return TRUE;
+                               }
+                               case IDC_SHUTDOWN:
+                               {
+                                       EndDialog(hwndDlg, WLX_SAS_ACTION_SHUTDOWN);
+                                       return TRUE;
+                               }
+                       }
+                       break;
+               }
+       }
+
+       return FALSE;
+}
+
+static INT
+GUILoggedOutSAS(
+       IN OUT PGINA_CONTEXT pgContext)
+{
+       int result;
+
+       TRACE("GUILoggedOutSAS()\n");
+
+       result = pgContext->pWlxFuncs->WlxDialogBoxParam(
+               pgContext->hWlx,
+               pgContext->hDllInstance,
+               MAKEINTRESOURCEW(IDD_LOGGEDOUT_DLG),
+               NULL,
+               LoggedOutWindowProc,
+               (LPARAM)pgContext);
+       if (result >= WLX_SAS_ACTION_LOGON &&
+           result <= WLX_SAS_ACTION_SWITCH_CONSOLE)
+       {
+               WARN("WlxLoggedOutSAS() returns 0x%x\n", result);
+               return result;
+       }
+
+       WARN("WlxDialogBoxParam() failed (0x%x)\n", result);
+       return WLX_SAS_ACTION_NONE;
+}
+
+static INT
+GUILockedSAS(
+       IN OUT PGINA_CONTEXT pgContext)
+{
+       TRACE("GUILockedSAS()\n");
+
+       UNIMPLEMENTED;
+       return WLX_SAS_ACTION_UNLOCK_WKSTA;
+}
+
+GINA_UI GinaGraphicalUI = {
+       GUIInitialize,
+       GUIDisplayStatusMessage,
+       GUIRemoveStatusMessage,
+       GUIDisplaySASNotice,
+       GUILoggedOnSAS,
+       GUILoggedOutSAS,
+       GUILockedSAS,
+};