[WINLOGON]
[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 if (pgContext->bAutoAdminLogon == TRUE)
287 EnableWindow(GetDlgItem(hwnd, IDC_LOGOFF), FALSE);
288 }
289
290
291 static BOOL
292 OnChangePassword(
293 IN HWND hwnd,
294 IN PGINA_CONTEXT pgContext)
295 {
296 INT res;
297
298 FIXME("OnChangePassword()\n");
299
300 res = pgContext->pWlxFuncs->WlxDialogBoxParam(
301 pgContext->hWlx,
302 pgContext->hDllInstance,
303 MAKEINTRESOURCEW(IDD_CHANGE_PASSWORD),
304 hwnd,
305 ChangePasswordDialogProc,
306 (LPARAM)pgContext);
307
308 FIXME("Result: %x\n", res);
309
310 return FALSE;
311 }
312
313
314 static INT_PTR CALLBACK
315 LoggedOnWindowProc(
316 IN HWND hwndDlg,
317 IN UINT uMsg,
318 IN WPARAM wParam,
319 IN LPARAM lParam)
320 {
321 PGINA_CONTEXT pgContext;
322
323 pgContext = (PGINA_CONTEXT)GetWindowLongPtr(hwndDlg, GWL_USERDATA);
324
325 switch (uMsg)
326 {
327 case WM_INITDIALOG:
328 {
329 pgContext = (PGINA_CONTEXT)lParam;
330 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)pgContext);
331
332 OnInitSecurityDlg(hwndDlg, (PGINA_CONTEXT)lParam);
333 SetFocus(GetDlgItem(hwndDlg, IDNO));
334 return TRUE;
335 }
336
337 case WM_COMMAND:
338 {
339 switch (LOWORD(wParam))
340 {
341 case IDC_LOCK:
342 EndDialog(hwndDlg, WLX_SAS_ACTION_LOCK_WKSTA);
343 return TRUE;
344 case IDC_LOGOFF:
345 EndDialog(hwndDlg, WLX_SAS_ACTION_LOGOFF);
346 return TRUE;
347 case IDC_SHUTDOWN:
348 EndDialog(hwndDlg, WLX_SAS_ACTION_SHUTDOWN_POWER_OFF);
349 return TRUE;
350 case IDC_CHANGEPWD:
351 if (OnChangePassword(hwndDlg, pgContext))
352 EndDialog(hwndDlg, WLX_SAS_ACTION_PWD_CHANGED);
353 return TRUE;
354 case IDC_TASKMGR:
355 EndDialog(hwndDlg, WLX_SAS_ACTION_TASKLIST);
356 return TRUE;
357 case IDCANCEL:
358 EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
359 return TRUE;
360 }
361 break;
362 }
363 case WM_CLOSE:
364 {
365 EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
366 return TRUE;
367 }
368 }
369
370 return FALSE;
371 }
372
373 static INT
374 GUILoggedOnSAS(
375 IN OUT PGINA_CONTEXT pgContext,
376 IN DWORD dwSasType)
377 {
378 INT result;
379
380 TRACE("GUILoggedOnSAS()\n");
381
382 if (dwSasType != WLX_SAS_TYPE_CTRL_ALT_DEL)
383 {
384 /* Nothing to do for WLX_SAS_TYPE_TIMEOUT ; the dialog will
385 * close itself thanks to the use of WlxDialogBoxParam */
386 return WLX_SAS_ACTION_NONE;
387 }
388
389 pgContext->pWlxFuncs->WlxSwitchDesktopToWinlogon(
390 pgContext->hWlx);
391
392 result = pgContext->pWlxFuncs->WlxDialogBoxParam(
393 pgContext->hWlx,
394 pgContext->hDllInstance,
395 MAKEINTRESOURCEW(IDD_LOGGEDON_DLG),
396 GetDesktopWindow(),
397 LoggedOnWindowProc,
398 (LPARAM)pgContext);
399
400 if (result < WLX_SAS_ACTION_LOGON ||
401 result > WLX_SAS_ACTION_SWITCH_CONSOLE)
402 {
403 result = WLX_SAS_ACTION_NONE;
404 }
405
406 if (result == WLX_SAS_ACTION_NONE)
407 {
408 pgContext->pWlxFuncs->WlxSwitchDesktopToUser(
409 pgContext->hWlx);
410 }
411
412 return result;
413 }
414
415 static INT_PTR CALLBACK
416 LoggedOutWindowProc(
417 IN HWND hwndDlg,
418 IN UINT uMsg,
419 IN WPARAM wParam,
420 IN LPARAM lParam)
421 {
422 PGINA_CONTEXT pgContext;
423
424 pgContext = (PGINA_CONTEXT)GetWindowLongPtr(hwndDlg, GWL_USERDATA);
425
426 switch (uMsg)
427 {
428 case WM_INITDIALOG:
429 {
430 /* FIXME: take care of DontDisplayLastUserName, NoDomainUI, ShutdownWithoutLogon */
431 pgContext = (PGINA_CONTEXT)lParam;
432 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)pgContext);
433
434 if (pgContext->bDisableCAD == TRUE)
435 EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), FALSE);
436
437 SetFocus(GetDlgItem(hwndDlg, IDC_USERNAME));
438
439 pgContext->hBitmap = LoadImage(hDllInstance, MAKEINTRESOURCE(IDI_ROSLOGO), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
440 return TRUE;
441 }
442 case WM_PAINT:
443 {
444 PAINTSTRUCT ps;
445 HDC hdc;
446 if (pgContext->hBitmap)
447 {
448 hdc = BeginPaint(hwndDlg, &ps);
449 DrawStateW(hdc, NULL, NULL, (LPARAM)pgContext->hBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);
450 EndPaint(hwndDlg, &ps);
451 }
452 return TRUE;
453 }
454 case WM_DESTROY:
455 {
456 DeleteObject(pgContext->hBitmap);
457 return TRUE;
458 }
459 case WM_COMMAND:
460 {
461 switch (LOWORD(wParam))
462 {
463 case IDOK:
464 {
465 LPWSTR UserName = NULL, Password = NULL;
466 INT result = WLX_SAS_ACTION_NONE;
467
468 if (GetTextboxText(hwndDlg, IDC_USERNAME, &UserName) && *UserName == '\0')
469 break;
470 if (GetTextboxText(hwndDlg, IDC_PASSWORD, &Password) &&
471 DoLoginTasks(pgContext, UserName, NULL, Password))
472 {
473 result = WLX_SAS_ACTION_LOGON;
474 }
475 HeapFree(GetProcessHeap(), 0, UserName);
476 HeapFree(GetProcessHeap(), 0, Password);
477 EndDialog(hwndDlg, result);
478 return TRUE;
479 }
480 case IDCANCEL:
481 {
482 EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
483 return TRUE;
484 }
485 case IDC_SHUTDOWN:
486 {
487 EndDialog(hwndDlg, WLX_SAS_ACTION_SHUTDOWN);
488 return TRUE;
489 }
490 }
491 break;
492 }
493 }
494
495 return FALSE;
496 }
497
498 static INT
499 GUILoggedOutSAS(
500 IN OUT PGINA_CONTEXT pgContext)
501 {
502 int result;
503
504 TRACE("GUILoggedOutSAS()\n");
505
506 result = pgContext->pWlxFuncs->WlxDialogBoxParam(
507 pgContext->hWlx,
508 pgContext->hDllInstance,
509 MAKEINTRESOURCEW(IDD_LOGGEDOUT_DLG),
510 GetDesktopWindow(),
511 LoggedOutWindowProc,
512 (LPARAM)pgContext);
513 if (result >= WLX_SAS_ACTION_LOGON &&
514 result <= WLX_SAS_ACTION_SWITCH_CONSOLE)
515 {
516 WARN("WlxLoggedOutSAS() returns 0x%x\n", result);
517 return result;
518 }
519
520 WARN("WlxDialogBoxParam() failed (0x%x)\n", result);
521 return WLX_SAS_ACTION_NONE;
522 }
523
524
525 static
526 INT_PTR
527 CALLBACK
528 UnlockWindowProc(
529 IN HWND hwndDlg,
530 IN UINT uMsg,
531 IN WPARAM wParam,
532 IN LPARAM lParam)
533 {
534 PGINA_CONTEXT pgContext;
535
536 pgContext = (PGINA_CONTEXT)GetWindowLongPtr(hwndDlg, GWL_USERDATA);
537
538 switch (uMsg)
539 {
540 case WM_INITDIALOG:
541 pgContext = (PGINA_CONTEXT)lParam;
542 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)pgContext);
543
544 if (pgContext->bDisableCAD == TRUE)
545 EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), FALSE);
546
547 SetFocus(GetDlgItem(hwndDlg, IDC_USERNAME));
548
549 pgContext->hBitmap = LoadImage(hDllInstance, MAKEINTRESOURCE(IDI_ROSLOGO), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
550 return TRUE;
551
552 case WM_PAINT:
553 {
554 PAINTSTRUCT ps;
555 HDC hdc;
556 if (pgContext->hBitmap)
557 {
558 hdc = BeginPaint(hwndDlg, &ps);
559 DrawStateW(hdc, NULL, NULL, (LPARAM)pgContext->hBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);
560 EndPaint(hwndDlg, &ps);
561 }
562 return TRUE;
563 }
564 case WM_DESTROY:
565 DeleteObject(pgContext->hBitmap);
566 return TRUE;
567
568 case WM_COMMAND:
569 switch (LOWORD(wParam))
570 {
571 case IDOK:
572 {
573 #if 0
574 LPWSTR UserName = NULL, Password = NULL;
575 INT result = WLX_SAS_ACTION_NONE;
576
577 if (GetTextboxText(hwndDlg, IDC_USERNAME, &UserName) && *UserName == '\0')
578 break;
579 if (GetTextboxText(hwndDlg, IDC_PASSWORD, &Password) &&
580 DoLoginTasks(pgContext, UserName, NULL, Password))
581 {
582 result = WLX_SAS_ACTION_LOGON;
583 }
584 HeapFree(GetProcessHeap(), 0, UserName);
585 HeapFree(GetProcessHeap(), 0, Password);
586 EndDialog(hwndDlg, result);
587 #endif
588 EndDialog(hwndDlg, WLX_SAS_ACTION_UNLOCK_WKSTA);
589 return TRUE;
590 }
591
592 case IDCANCEL:
593 EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
594 return TRUE;
595 }
596 break;
597 }
598
599 return FALSE;
600 }
601
602
603 static INT
604 GUILockedSAS(
605 IN OUT PGINA_CONTEXT pgContext)
606 {
607 int result;
608
609 TRACE("GUILockedSAS()\n");
610
611 result = pgContext->pWlxFuncs->WlxDialogBoxParam(
612 pgContext->hWlx,
613 pgContext->hDllInstance,
614 MAKEINTRESOURCEW(IDD_UNLOCK_DLG),
615 GetDesktopWindow(),
616 UnlockWindowProc,
617 (LPARAM)pgContext);
618 if (result >= WLX_SAS_ACTION_LOGON &&
619 result <= WLX_SAS_ACTION_SWITCH_CONSOLE)
620 {
621 WARN("GUILockedSAS() returns 0x%x\n", result);
622 return result;
623 }
624
625 WARN("GUILockedSAS() failed (0x%x)\n", result);
626 return WLX_SAS_ACTION_NONE;
627 }
628
629
630 static VOID
631 OnInitLockedDlg(HWND hwnd,
632 PGINA_CONTEXT pgContext)
633 {
634 WCHAR Buffer1[256];
635 WCHAR Buffer2[256];
636 WCHAR Buffer3[512];
637
638 LoadStringW(pgContext->hDllInstance, IDS_LOCKMSG, Buffer1, 256);
639
640 wsprintfW(Buffer2, L"%s\\%s", pgContext->Domain, pgContext->UserName);
641 wsprintfW(Buffer3, Buffer1, Buffer2);
642
643 SetDlgItemTextW(hwnd, IDC_LOCKMSG, Buffer3);
644 }
645
646
647 static INT_PTR CALLBACK
648 LockedWindowProc(
649 IN HWND hwndDlg,
650 IN UINT uMsg,
651 IN WPARAM wParam,
652 IN LPARAM lParam)
653 {
654 PGINA_CONTEXT pgContext;
655
656 pgContext = (PGINA_CONTEXT)GetWindowLongPtr(hwndDlg, GWL_USERDATA);
657
658 switch (uMsg)
659 {
660 case WM_INITDIALOG:
661 {
662 pgContext = (PGINA_CONTEXT)lParam;
663 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)pgContext);
664
665 pgContext->hBitmap = LoadImage(hDllInstance, MAKEINTRESOURCE(IDI_ROSLOGO), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
666 OnInitLockedDlg(hwndDlg, pgContext);
667 return TRUE;
668 }
669 case WM_PAINT:
670 {
671 PAINTSTRUCT ps;
672 HDC hdc;
673 if (pgContext->hBitmap)
674 {
675 hdc = BeginPaint(hwndDlg, &ps);
676 DrawStateW(hdc, NULL, NULL, (LPARAM)pgContext->hBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);
677 EndPaint(hwndDlg, &ps);
678 }
679 return TRUE;
680 }
681 case WM_DESTROY:
682 {
683 DeleteObject(pgContext->hBitmap);
684 return TRUE;
685 }
686 }
687
688 return FALSE;
689 }
690
691
692 static VOID
693 GUIDisplayLockedNotice(
694 IN OUT PGINA_CONTEXT pgContext)
695 {
696 TRACE("GUIdisplayLockedNotice()\n");
697
698 pgContext->pWlxFuncs->WlxDialogBoxParam(
699 pgContext->hWlx,
700 pgContext->hDllInstance,
701 MAKEINTRESOURCEW(IDD_LOCKED_DLG),
702 GetDesktopWindow(),
703 LockedWindowProc,
704 (LPARAM)pgContext);
705 }
706
707 GINA_UI GinaGraphicalUI = {
708 GUIInitialize,
709 GUIDisplayStatusMessage,
710 GUIRemoveStatusMessage,
711 GUIDisplaySASNotice,
712 GUILoggedOnSAS,
713 GUILoggedOutSAS,
714 GUILockedSAS,
715 GUIDisplayLockedNotice,
716 };