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