[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 typedef struct _DISPLAYSTATUSMSG
11 {
12 PGINA_CONTEXT Context;
13 HDESK hDesktop;
14 DWORD dwOptions;
15 PWSTR pTitle;
16 PWSTR pMessage;
17 HANDLE StartupEvent;
18 } DISPLAYSTATUSMSG, *PDISPLAYSTATUSMSG;
19
20 static BOOL
21 GUIInitialize(
22 IN OUT PGINA_CONTEXT pgContext)
23 {
24 TRACE("GUIInitialize(%p)\n", pgContext);
25 return TRUE;
26 }
27
28 static INT_PTR CALLBACK
29 StatusMessageWindowProc(
30 IN HWND hwndDlg,
31 IN UINT uMsg,
32 IN WPARAM wParam,
33 IN LPARAM lParam)
34 {
35 UNREFERENCED_PARAMETER(wParam);
36
37 switch (uMsg)
38 {
39 case WM_INITDIALOG:
40 {
41 PDISPLAYSTATUSMSG msg = (PDISPLAYSTATUSMSG)lParam;
42 if (!msg)
43 return FALSE;
44
45 msg->Context->hStatusWindow = hwndDlg;
46
47 if (msg->pTitle)
48 SetWindowTextW(hwndDlg, msg->pTitle);
49 SetDlgItemTextW(hwndDlg, IDC_STATUSLABEL, msg->pMessage);
50 SetEvent(msg->StartupEvent);
51 return TRUE;
52 }
53 }
54 return FALSE;
55 }
56
57 static DWORD WINAPI
58 StartupWindowThread(LPVOID lpParam)
59 {
60 HDESK hDesk;
61 PDISPLAYSTATUSMSG msg = (PDISPLAYSTATUSMSG)lpParam;
62
63 /* When SetThreadDesktop is called the system closes the desktop handle when needed
64 so we have to create a new handle because this handle may still be in use by winlogon */
65 if (!DuplicateHandle ( GetCurrentProcess(),
66 msg->hDesktop,
67 GetCurrentProcess(),
68 (HANDLE*)&hDesk,
69 0,
70 FALSE,
71 DUPLICATE_SAME_ACCESS))
72 {
73 HeapFree(GetProcessHeap(), 0, lpParam);
74 return FALSE;
75 }
76
77 if(!SetThreadDesktop(hDesk))
78 {
79 HeapFree(GetProcessHeap(), 0, lpParam);
80 return FALSE;
81 }
82
83 DialogBoxParam(
84 hDllInstance,
85 MAKEINTRESOURCE(IDD_STATUSWINDOW_DLG),
86 GetDesktopWindow(),
87 StatusMessageWindowProc,
88 (LPARAM)lpParam);
89
90 HeapFree(GetProcessHeap(), 0, lpParam);
91 return TRUE;
92 }
93
94 static BOOL
95 GUIDisplayStatusMessage(
96 IN PGINA_CONTEXT pgContext,
97 IN HDESK hDesktop,
98 IN DWORD dwOptions,
99 IN PWSTR pTitle,
100 IN PWSTR pMessage)
101 {
102 PDISPLAYSTATUSMSG msg;
103 HANDLE Thread;
104 DWORD ThreadId;
105
106 TRACE("GUIDisplayStatusMessage(%ws)\n", pMessage);
107
108 if (!pgContext->hStatusWindow)
109 {
110 msg = (PDISPLAYSTATUSMSG)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DISPLAYSTATUSMSG));
111 if(!msg)
112 return FALSE;
113
114 msg->Context = pgContext;
115 msg->dwOptions = dwOptions;
116 msg->pTitle = pTitle;
117 msg->pMessage = pMessage;
118 msg->hDesktop = hDesktop;
119
120 msg->StartupEvent = CreateEventW(
121 NULL,
122 TRUE,
123 FALSE,
124 NULL);
125
126 if (!msg->StartupEvent)
127 return FALSE;
128
129 Thread = CreateThread(
130 NULL,
131 0,
132 StartupWindowThread,
133 (PVOID)msg,
134 0,
135 &ThreadId);
136 if (Thread)
137 {
138 CloseHandle(Thread);
139 WaitForSingleObject(msg->StartupEvent, INFINITE);
140 CloseHandle(msg->StartupEvent);
141 return TRUE;
142 }
143
144 return FALSE;
145 }
146
147 if (pTitle)
148 SetWindowTextW(pgContext->hStatusWindow, pTitle);
149
150 SetDlgItemTextW(pgContext->hStatusWindow, IDC_STATUSLABEL, pMessage);
151
152 return TRUE;
153 }
154
155 static BOOL
156 GUIRemoveStatusMessage(
157 IN PGINA_CONTEXT pgContext)
158 {
159 if (pgContext->hStatusWindow)
160 {
161 EndDialog(pgContext->hStatusWindow, 0);
162 pgContext->hStatusWindow = NULL;
163 }
164
165 return TRUE;
166 }
167
168 static INT_PTR CALLBACK
169 EmptyWindowProc(
170 IN HWND hwndDlg,
171 IN UINT uMsg,
172 IN WPARAM wParam,
173 IN LPARAM lParam)
174 {
175 UNREFERENCED_PARAMETER(hwndDlg);
176 UNREFERENCED_PARAMETER(uMsg);
177 UNREFERENCED_PARAMETER(wParam);
178 UNREFERENCED_PARAMETER(lParam);
179
180 return FALSE;
181 }
182
183 static VOID
184 GUIDisplaySASNotice(
185 IN OUT PGINA_CONTEXT pgContext)
186 {
187 TRACE("GUIDisplaySASNotice()\n");
188
189 /* Display the notice window */
190 pgContext->pWlxFuncs->WlxDialogBoxParam(pgContext->hWlx,
191 pgContext->hDllInstance,
192 MAKEINTRESOURCEW(IDD_NOTICE_DLG),
193 GetDesktopWindow(),
194 EmptyWindowProc,
195 (LPARAM)NULL);
196 }
197
198 /* Get the text contained in a textbox. Allocates memory in pText
199 * to contain the text. Returns TRUE in case of success */
200 static BOOL
201 GetTextboxText(
202 IN HWND hwndDlg,
203 IN INT TextboxId,
204 OUT LPWSTR *pText)
205 {
206 LPWSTR Text;
207 int Count;
208
209 Count = GetWindowTextLength(GetDlgItem(hwndDlg, TextboxId));
210 Text = HeapAlloc(GetProcessHeap(), 0, (Count + 1) * sizeof(WCHAR));
211 if (!Text)
212 return FALSE;
213 if (Count != GetWindowTextW(GetDlgItem(hwndDlg, TextboxId), Text, Count + 1))
214 {
215 HeapFree(GetProcessHeap(), 0, Text);
216 return FALSE;
217 }
218 *pText = Text;
219 return TRUE;
220 }
221
222
223 static INT_PTR CALLBACK
224 ChangePasswordDialogProc(
225 IN HWND hwndDlg,
226 IN UINT uMsg,
227 IN WPARAM wParam,
228 IN LPARAM lParam)
229 {
230 switch (uMsg)
231 {
232 case WM_INITDIALOG:
233 FIXME("ChangePasswordDialogProc: WM_INITDLG\n");
234 return TRUE;
235
236 case WM_COMMAND:
237 switch (LOWORD(wParam))
238 {
239 case IDOK:
240 EndDialog(hwndDlg, TRUE);
241 return TRUE;
242
243 case IDCANCEL:
244 EndDialog(hwndDlg, FALSE);
245 return TRUE;
246 }
247 break;
248
249 case WM_CLOSE:
250 EndDialog(hwndDlg, FALSE);
251 return TRUE;
252 }
253
254 return FALSE;
255 }
256
257
258 static VOID
259 OnInitSecurityDlg(HWND hwnd,
260 PGINA_CONTEXT pgContext)
261 {
262 WCHAR Buffer1[256];
263 WCHAR Buffer2[256];
264 WCHAR Buffer3[256];
265 WCHAR Buffer4[512];
266
267 LoadStringW(pgContext->hDllInstance, IDS_LOGONMSG, Buffer1, 256);
268
269 wsprintfW(Buffer2, L"%s\\%s", pgContext->Domain, pgContext->UserName);
270 wsprintfW(Buffer4, Buffer1, Buffer2);
271
272 SetDlgItemTextW(hwnd, IDC_LOGONMSG, Buffer4);
273
274 LoadStringW(pgContext->hDllInstance, IDS_LOGONDATE, Buffer1, 256);
275
276 GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE,
277 (SYSTEMTIME*)&pgContext->LogonTime, NULL, Buffer2, 256);
278
279 GetTimeFormatW(LOCALE_USER_DEFAULT, 0,
280 (SYSTEMTIME*)&pgContext->LogonTime, NULL, Buffer3, 256);
281
282 wsprintfW(Buffer4, Buffer1, Buffer2, Buffer3);
283
284 SetDlgItemTextW(hwnd, IDC_LOGONDATE, Buffer4);
285 }
286
287
288 static BOOL
289 OnChangePassword(
290 IN HWND hwnd,
291 IN PGINA_CONTEXT pgContext)
292 {
293 INT res;
294
295 FIXME("OnChangePassword()\n");
296
297 res = pgContext->pWlxFuncs->WlxDialogBoxParam(
298 pgContext->hWlx,
299 pgContext->hDllInstance,
300 MAKEINTRESOURCEW(IDD_CHANGE_PASSWORD),
301 hwnd,
302 ChangePasswordDialogProc,
303 (LPARAM)pgContext);
304
305 FIXME("Result: %x\n", res);
306
307 return FALSE;
308 }
309
310
311 static INT_PTR CALLBACK
312 LoggedOnWindowProc(
313 IN HWND hwndDlg,
314 IN UINT uMsg,
315 IN WPARAM wParam,
316 IN LPARAM lParam)
317 {
318 PGINA_CONTEXT pgContext;
319
320 pgContext = (PGINA_CONTEXT)GetWindowLongPtr(hwndDlg, GWL_USERDATA);
321
322 switch (uMsg)
323 {
324 case WM_INITDIALOG:
325 {
326 pgContext = (PGINA_CONTEXT)lParam;
327 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)pgContext);
328
329 OnInitSecurityDlg(hwndDlg, (PGINA_CONTEXT)lParam);
330 SetFocus(GetDlgItem(hwndDlg, IDNO));
331 return TRUE;
332 }
333
334 case WM_COMMAND:
335 {
336 switch (LOWORD(wParam))
337 {
338 case IDC_LOCK:
339 EndDialog(hwndDlg, WLX_SAS_ACTION_LOCK_WKSTA);
340 return TRUE;
341 case IDC_LOGOFF:
342 EndDialog(hwndDlg, WLX_SAS_ACTION_LOGOFF);
343 return TRUE;
344 case IDC_SHUTDOWN:
345 EndDialog(hwndDlg, WLX_SAS_ACTION_SHUTDOWN_POWER_OFF);
346 return TRUE;
347 case IDC_CHANGEPWD:
348 if (OnChangePassword(hwndDlg, pgContext))
349 EndDialog(hwndDlg, WLX_SAS_ACTION_PWD_CHANGED);
350 return TRUE;
351 case IDC_TASKMGR:
352 EndDialog(hwndDlg, WLX_SAS_ACTION_TASKLIST);
353 return TRUE;
354 case IDCANCEL:
355 EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
356 return TRUE;
357 }
358 break;
359 }
360 case WM_CLOSE:
361 {
362 EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
363 return TRUE;
364 }
365 }
366
367 return FALSE;
368 }
369
370 static INT
371 GUILoggedOnSAS(
372 IN OUT PGINA_CONTEXT pgContext,
373 IN DWORD dwSasType)
374 {
375 INT result;
376
377 TRACE("GUILoggedOnSAS()\n");
378
379 if (dwSasType != WLX_SAS_TYPE_CTRL_ALT_DEL)
380 {
381 /* Nothing to do for WLX_SAS_TYPE_TIMEOUT ; the dialog will
382 * close itself thanks to the use of WlxDialogBoxParam */
383 return WLX_SAS_ACTION_NONE;
384 }
385
386 result = pgContext->pWlxFuncs->WlxSwitchDesktopToWinlogon(
387 pgContext->hWlx);
388
389 result = pgContext->pWlxFuncs->WlxDialogBoxParam(
390 pgContext->hWlx,
391 pgContext->hDllInstance,
392 MAKEINTRESOURCEW(IDD_LOGGEDON_DLG),
393 GetDesktopWindow(),
394 LoggedOnWindowProc,
395 (LPARAM)pgContext);
396
397 if (result < WLX_SAS_ACTION_LOGON ||
398 result > WLX_SAS_ACTION_SWITCH_CONSOLE)
399 {
400 result = WLX_SAS_ACTION_NONE;
401 }
402
403 if (result == WLX_SAS_ACTION_NONE)
404 {
405 result = pgContext->pWlxFuncs->WlxSwitchDesktopToUser(
406 pgContext->hWlx);
407 }
408
409 return result;
410 }
411
412 static INT_PTR CALLBACK
413 LoggedOutWindowProc(
414 IN HWND hwndDlg,
415 IN UINT uMsg,
416 IN WPARAM wParam,
417 IN LPARAM lParam)
418 {
419 PGINA_CONTEXT pgContext;
420
421 pgContext = (PGINA_CONTEXT)GetWindowLongPtr(hwndDlg, GWL_USERDATA);
422
423 switch (uMsg)
424 {
425 case WM_INITDIALOG:
426 {
427 /* FIXME: take care of DontDisplayLastUserName, NoDomainUI, ShutdownWithoutLogon */
428 pgContext = (PGINA_CONTEXT)lParam;
429 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)pgContext);
430 SetFocus(GetDlgItem(hwndDlg, IDC_USERNAME));
431
432 pgContext->hBitmap = LoadImage(hDllInstance, MAKEINTRESOURCE(IDI_ROSLOGO), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
433 return TRUE;
434 }
435 case WM_PAINT:
436 {
437 PAINTSTRUCT ps;
438 HDC hdc;
439 if (pgContext->hBitmap)
440 {
441 hdc = BeginPaint(hwndDlg, &ps);
442 DrawStateW(hdc, NULL, NULL, (LPARAM)pgContext->hBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);
443 EndPaint(hwndDlg, &ps);
444 }
445 return TRUE;
446 }
447 case WM_DESTROY:
448 {
449 DeleteObject(pgContext->hBitmap);
450 return TRUE;
451 }
452 case WM_COMMAND:
453 {
454 switch (LOWORD(wParam))
455 {
456 case IDOK:
457 {
458 LPWSTR UserName = NULL, Password = NULL;
459 INT result = WLX_SAS_ACTION_NONE;
460
461 if (GetTextboxText(hwndDlg, IDC_USERNAME, &UserName) && *UserName == '\0')
462 break;
463 if (GetTextboxText(hwndDlg, IDC_PASSWORD, &Password) &&
464 DoLoginTasks(pgContext, UserName, NULL, Password))
465 {
466 result = WLX_SAS_ACTION_LOGON;
467 }
468 HeapFree(GetProcessHeap(), 0, UserName);
469 HeapFree(GetProcessHeap(), 0, Password);
470 EndDialog(hwndDlg, result);
471 return TRUE;
472 }
473 case IDCANCEL:
474 {
475 EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
476 return TRUE;
477 }
478 case IDC_SHUTDOWN:
479 {
480 EndDialog(hwndDlg, WLX_SAS_ACTION_SHUTDOWN);
481 return TRUE;
482 }
483 }
484 break;
485 }
486 }
487
488 return FALSE;
489 }
490
491 static INT
492 GUILoggedOutSAS(
493 IN OUT PGINA_CONTEXT pgContext)
494 {
495 int result;
496
497 TRACE("GUILoggedOutSAS()\n");
498
499 result = pgContext->pWlxFuncs->WlxDialogBoxParam(
500 pgContext->hWlx,
501 pgContext->hDllInstance,
502 MAKEINTRESOURCEW(IDD_LOGGEDOUT_DLG),
503 GetDesktopWindow(),
504 LoggedOutWindowProc,
505 (LPARAM)pgContext);
506 if (result >= WLX_SAS_ACTION_LOGON &&
507 result <= WLX_SAS_ACTION_SWITCH_CONSOLE)
508 {
509 WARN("WlxLoggedOutSAS() returns 0x%x\n", result);
510 return result;
511 }
512
513 WARN("WlxDialogBoxParam() failed (0x%x)\n", result);
514 return WLX_SAS_ACTION_NONE;
515 }
516
517 static INT
518 GUILockedSAS(
519 IN OUT PGINA_CONTEXT pgContext)
520 {
521 TRACE("GUILockedSAS()\n");
522
523 UNREFERENCED_PARAMETER(pgContext);
524
525 UNIMPLEMENTED;
526 return WLX_SAS_ACTION_UNLOCK_WKSTA;
527 }
528
529
530 static VOID
531 OnInitLockedDlg(HWND hwnd,
532 PGINA_CONTEXT pgContext)
533 {
534 WCHAR Buffer1[256];
535 WCHAR Buffer2[256];
536 WCHAR Buffer3[512];
537
538 LoadStringW(pgContext->hDllInstance, IDS_LOCKMSG, Buffer1, 256);
539
540 wsprintfW(Buffer2, L"%s\\%s", pgContext->Domain, pgContext->UserName);
541 wsprintfW(Buffer3, Buffer1, Buffer2);
542
543 SetDlgItemTextW(hwnd, IDC_LOCKMSG, Buffer3);
544 }
545
546
547 static INT_PTR CALLBACK
548 LockedWindowProc(
549 IN HWND hwndDlg,
550 IN UINT uMsg,
551 IN WPARAM wParam,
552 IN LPARAM lParam)
553 {
554 PGINA_CONTEXT pgContext;
555
556 pgContext = (PGINA_CONTEXT)GetWindowLongPtr(hwndDlg, GWL_USERDATA);
557
558 switch (uMsg)
559 {
560 case WM_INITDIALOG:
561 {
562 pgContext = (PGINA_CONTEXT)lParam;
563 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)pgContext);
564
565 pgContext->hBitmap = LoadImage(hDllInstance, MAKEINTRESOURCE(IDI_ROSLOGO), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
566 OnInitLockedDlg(hwndDlg, pgContext);
567 return TRUE;
568 }
569 case WM_PAINT:
570 {
571 PAINTSTRUCT ps;
572 HDC hdc;
573 if (pgContext->hBitmap)
574 {
575 hdc = BeginPaint(hwndDlg, &ps);
576 DrawStateW(hdc, NULL, NULL, (LPARAM)pgContext->hBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);
577 EndPaint(hwndDlg, &ps);
578 }
579 return TRUE;
580 }
581 case WM_DESTROY:
582 {
583 DeleteObject(pgContext->hBitmap);
584 return TRUE;
585 }
586 }
587
588 return FALSE;
589 }
590
591
592 static VOID
593 GUIDisplayLockedNotice(
594 IN OUT PGINA_CONTEXT pgContext)
595 {
596 TRACE("GUIdisplayLockedNotice()\n");
597
598 pgContext->pWlxFuncs->WlxDialogBoxParam(
599 pgContext->hWlx,
600 pgContext->hDllInstance,
601 MAKEINTRESOURCEW(IDD_LOCKED_DLG),
602 GetDesktopWindow(),
603 LockedWindowProc,
604 (LPARAM)pgContext);
605 }
606
607 GINA_UI GinaGraphicalUI = {
608 GUIInitialize,
609 GUIDisplayStatusMessage,
610 GUIRemoveStatusMessage,
611 GUIDisplaySASNotice,
612 GUILoggedOnSAS,
613 GUILoggedOutSAS,
614 GUILockedSAS,
615 GUIDisplayLockedNotice,
616 };