Jeffrey Morlan (mrnobo1024@yahoo.com)
[reactos.git] / reactos / dll / win32 / msgina / gui.c
1 /*
2 * PROJECT: ReactOS msgina.dll
3 * FILE: dll/win32/msgina/gui.c
4 * PURPOSE: ReactOS Logon GINA DLL
5 * PROGRAMMER: Hervé Poussineau (hpoussin@reactos.org)
6 */
7
8 #include "msgina.h"
9
10 #include <wine/debug.h>
11
12 WINE_DEFAULT_DEBUG_CHANNEL(msgina);
13
14 typedef struct _DISPLAYSTATUSMSG
15 {
16 PGINA_CONTEXT Context;
17 HDESK hDesktop;
18 DWORD dwOptions;
19 PWSTR pTitle;
20 PWSTR pMessage;
21 HANDLE StartupEvent;
22 } DISPLAYSTATUSMSG, *PDISPLAYSTATUSMSG;
23
24 static BOOL
25 GUIInitialize(
26 IN OUT PGINA_CONTEXT pgContext)
27 {
28 TRACE("GUIInitialize(%p)\n", pgContext);
29 return TRUE;
30 }
31
32 static BOOL CALLBACK
33 StatusMessageWindowProc(
34 IN HWND hwndDlg,
35 IN UINT uMsg,
36 IN WPARAM wParam,
37 IN LPARAM lParam)
38 {
39 UNREFERENCED_PARAMETER(wParam);
40
41 switch (uMsg)
42 {
43 case WM_INITDIALOG:
44 {
45 PDISPLAYSTATUSMSG msg = (PDISPLAYSTATUSMSG)lParam;
46 if (!msg)
47 return FALSE;
48
49 msg->Context->hStatusWindow = hwndDlg;
50
51 if (msg->pTitle)
52 SetWindowTextW(hwndDlg, msg->pTitle);
53 SetDlgItemTextW(hwndDlg, IDC_STATUSLABEL, msg->pMessage);
54 if (!msg->Context->SignaledStatusWindowCreated)
55 {
56 msg->Context->SignaledStatusWindowCreated = TRUE;
57 SetEvent(msg->StartupEvent);
58 }
59 return TRUE;
60 }
61 }
62 return FALSE;
63 }
64
65 static DWORD WINAPI
66 StartupWindowThread(LPVOID lpParam)
67 {
68 HDESK OldDesk;
69 PDISPLAYSTATUSMSG msg = (PDISPLAYSTATUSMSG)lpParam;
70
71 OldDesk = GetThreadDesktop(GetCurrentThreadId());
72
73 if(!SetThreadDesktop(msg->hDesktop))
74 {
75 HeapFree(GetProcessHeap(), 0, lpParam);
76 return FALSE;
77 }
78 DialogBoxParam(
79 hDllInstance,
80 MAKEINTRESOURCE(IDD_STATUSWINDOW_DLG),
81 GetDesktopWindow(),
82 StatusMessageWindowProc,
83 (LPARAM)lpParam);
84 SetThreadDesktop(OldDesk);
85
86 HeapFree(GetProcessHeap(), 0, lpParam);
87 return TRUE;
88 }
89
90 static BOOL
91 GUIDisplayStatusMessage(
92 IN PGINA_CONTEXT pgContext,
93 IN HDESK hDesktop,
94 IN DWORD dwOptions,
95 IN PWSTR pTitle,
96 IN PWSTR pMessage)
97 {
98 PDISPLAYSTATUSMSG msg;
99 HANDLE Thread;
100 DWORD ThreadId;
101
102 TRACE("GUIDisplayStatusMessage(%ws)\n", pMessage);
103
104 if (!pgContext->hStatusWindow)
105 {
106 msg = (PDISPLAYSTATUSMSG)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DISPLAYSTATUSMSG));
107 if(!msg)
108 return FALSE;
109
110 msg->Context = pgContext;
111 msg->dwOptions = dwOptions;
112 msg->pTitle = pTitle;
113 msg->pMessage = pMessage;
114 msg->hDesktop = hDesktop;
115
116 msg->StartupEvent = CreateEventW(
117 NULL,
118 TRUE,
119 FALSE,
120 NULL);
121
122 if (!msg->StartupEvent)
123 return FALSE;
124
125 Thread = CreateThread(
126 NULL,
127 0,
128 StartupWindowThread,
129 (PVOID)msg,
130 0,
131 &ThreadId);
132 if (Thread)
133 {
134 CloseHandle(Thread);
135 WaitForSingleObject(msg->StartupEvent, INFINITE);
136 CloseHandle(msg->StartupEvent);
137 return TRUE;
138 }
139
140 return FALSE;
141 }
142
143 if(pTitle)
144 SetWindowTextW(pgContext->hStatusWindow, pTitle);
145
146 SetDlgItemTextW(pgContext->hStatusWindow, IDC_STATUSLABEL, pMessage);
147
148 return TRUE;
149 }
150
151 static BOOL
152 GUIRemoveStatusMessage(
153 IN PGINA_CONTEXT pgContext)
154 {
155 if (pgContext->hStatusWindow)
156 {
157 EndDialog(pgContext->hStatusWindow, 0);
158 pgContext->hStatusWindow = 0;
159 pgContext->SignaledStatusWindowCreated = FALSE;
160 }
161
162 return TRUE;
163 }
164
165 static INT_PTR CALLBACK
166 EmptyWindowProc(
167 IN HWND hwndDlg,
168 IN UINT uMsg,
169 IN WPARAM wParam,
170 IN LPARAM lParam)
171 {
172 UNREFERENCED_PARAMETER(hwndDlg);
173 UNREFERENCED_PARAMETER(uMsg);
174 UNREFERENCED_PARAMETER(wParam);
175 UNREFERENCED_PARAMETER(lParam);
176
177 return FALSE;
178 }
179
180 static VOID
181 GUIDisplaySASNotice(
182 IN OUT PGINA_CONTEXT pgContext)
183 {
184 INT result;
185
186 TRACE("GUIDisplaySASNotice()\n");
187
188 /* Display the notice window */
189 result = DialogBoxParam(
190 pgContext->hDllInstance,
191 MAKEINTRESOURCE(IDD_NOTICE_DLG),
192 GetDesktopWindow(),
193 EmptyWindowProc,
194 (LPARAM)NULL);
195 if (result == -1)
196 {
197 /* Failed to display the window. Do as if the user
198 * already has pressed CTRL+ALT+DELETE */
199 pgContext->pWlxFuncs->WlxSasNotify(pgContext->hWlx, WLX_SAS_TYPE_CTRL_ALT_DEL);
200 }
201 }
202
203 /* Get the text contained in a textbox. Allocates memory in pText
204 * to contain the text. Returns TRUE in case of success */
205 static BOOL
206 GetTextboxText(
207 IN HWND hwndDlg,
208 IN INT TextboxId,
209 OUT LPWSTR *pText)
210 {
211 LPWSTR Text;
212 int Count;
213
214 Count = GetWindowTextLength(GetDlgItem(hwndDlg, TextboxId));
215 Text = HeapAlloc(GetProcessHeap(), 0, (Count + 1) * sizeof(WCHAR));
216 if (!Text)
217 return FALSE;
218 if (Count != GetWindowTextW(GetDlgItem(hwndDlg, TextboxId), Text, Count + 1))
219 {
220 HeapFree(GetProcessHeap(), 0, Text);
221 return FALSE;
222 }
223 *pText = Text;
224 return TRUE;
225 }
226
227 static INT_PTR CALLBACK
228 LoggedOnWindowProc(
229 IN HWND hwndDlg,
230 IN UINT uMsg,
231 IN WPARAM wParam,
232 IN LPARAM lParam)
233 {
234 UNREFERENCED_PARAMETER(lParam);
235
236 switch (uMsg)
237 {
238 case WM_COMMAND:
239 {
240 switch (LOWORD(wParam))
241 {
242 case IDC_LOCK:
243 EndDialog(hwndDlg, WLX_SAS_ACTION_LOCK_WKSTA);
244 return TRUE;
245 case IDC_LOGOFF:
246 EndDialog(hwndDlg, WLX_SAS_ACTION_LOGOFF);
247 return TRUE;
248 case IDC_SHUTDOWN:
249 EndDialog(hwndDlg, WLX_SAS_ACTION_SHUTDOWN_POWER_OFF);
250 return TRUE;
251 case IDC_TASKMGR:
252 EndDialog(hwndDlg, WLX_SAS_ACTION_TASKLIST);
253 return TRUE;
254 case IDCANCEL:
255 EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
256 return TRUE;
257 }
258 break;
259 }
260 case WM_INITDIALOG:
261 {
262 SetFocus(GetDlgItem(hwndDlg, IDNO));
263 return TRUE;
264 }
265 case WM_CLOSE:
266 {
267 EndDialog(hwndDlg, IDNO);
268 return TRUE;
269 }
270 }
271
272 return FALSE;
273 }
274
275 static INT
276 GUILoggedOnSAS(
277 IN OUT PGINA_CONTEXT pgContext,
278 IN DWORD dwSasType)
279 {
280 INT result;
281
282 TRACE("GUILoggedOnSAS()\n");
283
284 if (dwSasType != WLX_SAS_TYPE_CTRL_ALT_DEL)
285 {
286 /* Nothing to do for WLX_SAS_TYPE_TIMEOUT ; the dialog will
287 * close itself thanks to the use of WlxDialogBoxParam */
288 return WLX_SAS_ACTION_NONE;
289 }
290
291 result = pgContext->pWlxFuncs->WlxDialogBoxParam(
292 pgContext->hWlx,
293 pgContext->hDllInstance,
294 MAKEINTRESOURCEW(IDD_LOGGEDON_DLG),
295 GetDesktopWindow(),
296 LoggedOnWindowProc,
297 (LPARAM)pgContext);
298 if (result >= WLX_SAS_ACTION_LOGON &&
299 result <= WLX_SAS_ACTION_SWITCH_CONSOLE)
300 {
301 return result;
302 }
303 return WLX_SAS_ACTION_NONE;
304 }
305
306 static INT_PTR CALLBACK
307 LoggedOutWindowProc(
308 IN HWND hwndDlg,
309 IN UINT uMsg,
310 IN WPARAM wParam,
311 IN LPARAM lParam)
312 {
313 PGINA_CONTEXT pgContext;
314
315 pgContext = (PGINA_CONTEXT)GetWindowLongPtr(hwndDlg, GWL_USERDATA);
316
317 switch (uMsg)
318 {
319 case WM_INITDIALOG:
320 {
321 /* FIXME: take care of DontDisplayLastUserName, NoDomainUI, ShutdownWithoutLogon */
322 pgContext = (PGINA_CONTEXT)lParam;
323 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)pgContext);
324 SetFocus(GetDlgItem(hwndDlg, IDC_USERNAME));
325
326 pgContext->hBitmap = LoadImage(hDllInstance, MAKEINTRESOURCE(IDI_ROSLOGO), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
327 return TRUE;
328 }
329 case WM_PAINT:
330 {
331 PAINTSTRUCT ps;
332 HDC hdc;
333 if (pgContext->hBitmap)
334 {
335 hdc = BeginPaint(hwndDlg, &ps);
336 DrawStateW(hdc, NULL, NULL, (LPARAM)pgContext->hBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);
337 EndPaint(hwndDlg, &ps);
338 }
339 return TRUE;
340 }
341 case WM_DESTROY:
342 {
343 DeleteObject(pgContext->hBitmap);
344 return TRUE;
345 }
346 case WM_COMMAND:
347 {
348 switch (LOWORD(wParam))
349 {
350 case IDOK:
351 {
352 LPWSTR UserName = NULL, Password = NULL;
353 INT result = WLX_SAS_ACTION_NONE;
354
355 if (GetTextboxText(hwndDlg, IDC_USERNAME, &UserName) && *UserName == '\0')
356 break;
357 if (GetTextboxText(hwndDlg, IDC_PASSWORD, &Password) &&
358 DoLoginTasks(pgContext, UserName, NULL, Password))
359 {
360 result = WLX_SAS_ACTION_LOGON;
361 }
362 HeapFree(GetProcessHeap(), 0, UserName);
363 HeapFree(GetProcessHeap(), 0, Password);
364 EndDialog(hwndDlg, result);
365 return TRUE;
366 }
367 case IDCANCEL:
368 {
369 EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
370 return TRUE;
371 }
372 case IDC_SHUTDOWN:
373 {
374 EndDialog(hwndDlg, WLX_SAS_ACTION_SHUTDOWN);
375 return TRUE;
376 }
377 }
378 break;
379 }
380 }
381
382 return FALSE;
383 }
384
385 static INT
386 GUILoggedOutSAS(
387 IN OUT PGINA_CONTEXT pgContext)
388 {
389 int result;
390
391 TRACE("GUILoggedOutSAS()\n");
392
393 result = pgContext->pWlxFuncs->WlxDialogBoxParam(
394 pgContext->hWlx,
395 pgContext->hDllInstance,
396 MAKEINTRESOURCEW(IDD_LOGGEDOUT_DLG),
397 GetDesktopWindow(),
398 LoggedOutWindowProc,
399 (LPARAM)pgContext);
400 if (result >= WLX_SAS_ACTION_LOGON &&
401 result <= WLX_SAS_ACTION_SWITCH_CONSOLE)
402 {
403 WARN("WlxLoggedOutSAS() returns 0x%x\n", result);
404 return result;
405 }
406
407 WARN("WlxDialogBoxParam() failed (0x%x)\n", result);
408 return WLX_SAS_ACTION_NONE;
409 }
410
411 static INT
412 GUILockedSAS(
413 IN OUT PGINA_CONTEXT pgContext)
414 {
415 TRACE("GUILockedSAS()\n");
416
417 UNREFERENCED_PARAMETER(pgContext);
418
419 UNIMPLEMENTED;
420 return WLX_SAS_ACTION_UNLOCK_WKSTA;
421 }
422
423 GINA_UI GinaGraphicalUI = {
424 GUIInitialize,
425 GUIDisplayStatusMessage,
426 GUIRemoveStatusMessage,
427 GUIDisplaySASNotice,
428 GUILoggedOnSAS,
429 GUILoggedOutSAS,
430 GUILockedSAS,
431 };