804c98dc37554e08fc749900adda25ddb0bcd358
[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 <wingdi.h>
11 #include <winnls.h>
12
13 typedef struct _DISPLAYSTATUSMSG
14 {
15 PGINA_CONTEXT Context;
16 HDESK hDesktop;
17 DWORD dwOptions;
18 PWSTR pTitle;
19 PWSTR pMessage;
20 HANDLE StartupEvent;
21 } DISPLAYSTATUSMSG, *PDISPLAYSTATUSMSG;
22
23 static BOOL
24 GUIInitialize(
25 IN OUT PGINA_CONTEXT pgContext)
26 {
27 TRACE("GUIInitialize(%p)\n", pgContext);
28 return TRUE;
29 }
30
31 static INT_PTR CALLBACK
32 StatusMessageWindowProc(
33 IN HWND hwndDlg,
34 IN UINT uMsg,
35 IN WPARAM wParam,
36 IN LPARAM lParam)
37 {
38 UNREFERENCED_PARAMETER(wParam);
39
40 switch (uMsg)
41 {
42 case WM_INITDIALOG:
43 {
44 PDISPLAYSTATUSMSG msg = (PDISPLAYSTATUSMSG)lParam;
45 if (!msg)
46 return FALSE;
47
48 msg->Context->hStatusWindow = hwndDlg;
49
50 if (msg->pTitle)
51 SetWindowTextW(hwndDlg, msg->pTitle);
52 SetDlgItemTextW(hwndDlg, IDC_STATUSLABEL, msg->pMessage);
53 SetEvent(msg->StartupEvent);
54 return TRUE;
55 }
56 }
57 return FALSE;
58 }
59
60 static DWORD WINAPI
61 StartupWindowThread(LPVOID lpParam)
62 {
63 HDESK hDesk;
64 PDISPLAYSTATUSMSG msg = (PDISPLAYSTATUSMSG)lpParam;
65
66 /* When SetThreadDesktop is called the system closes the desktop handle when needed
67 so we have to create a new handle because this handle may still be in use by winlogon */
68 if (!DuplicateHandle ( GetCurrentProcess(),
69 msg->hDesktop,
70 GetCurrentProcess(),
71 (HANDLE*)&hDesk,
72 0,
73 FALSE,
74 DUPLICATE_SAME_ACCESS))
75 {
76 HeapFree(GetProcessHeap(), 0, lpParam);
77 return FALSE;
78 }
79
80 if(!SetThreadDesktop(hDesk))
81 {
82 HeapFree(GetProcessHeap(), 0, lpParam);
83 return FALSE;
84 }
85
86 DialogBoxParam(
87 hDllInstance,
88 MAKEINTRESOURCE(IDD_STATUSWINDOW_DLG),
89 GetDesktopWindow(),
90 StatusMessageWindowProc,
91 (LPARAM)lpParam);
92
93 HeapFree(GetProcessHeap(), 0, lpParam);
94 return TRUE;
95 }
96
97 static BOOL
98 GUIDisplayStatusMessage(
99 IN PGINA_CONTEXT pgContext,
100 IN HDESK hDesktop,
101 IN DWORD dwOptions,
102 IN PWSTR pTitle,
103 IN PWSTR pMessage)
104 {
105 PDISPLAYSTATUSMSG msg;
106 HANDLE Thread;
107 DWORD ThreadId;
108
109 TRACE("GUIDisplayStatusMessage(%ws)\n", pMessage);
110
111 if (!pgContext->hStatusWindow)
112 {
113 /*
114 * If everything goes correctly, 'msg' is freed
115 * by the 'StartupWindowThread' thread.
116 */
117 msg = (PDISPLAYSTATUSMSG)HeapAlloc(GetProcessHeap(),
118 HEAP_ZERO_MEMORY,
119 sizeof(DISPLAYSTATUSMSG));
120 if(!msg)
121 return FALSE;
122
123 msg->Context = pgContext;
124 msg->dwOptions = dwOptions;
125 msg->pTitle = pTitle;
126 msg->pMessage = pMessage;
127 msg->hDesktop = hDesktop;
128
129 msg->StartupEvent = CreateEventW(NULL,
130 TRUE,
131 FALSE,
132 NULL);
133
134 if (!msg->StartupEvent)
135 {
136 HeapFree(GetProcessHeap(), 0, msg);
137 return FALSE;
138 }
139
140 Thread = CreateThread(NULL,
141 0,
142 StartupWindowThread,
143 (PVOID)msg,
144 0,
145 &ThreadId);
146 if (Thread)
147 {
148 CloseHandle(Thread);
149 WaitForSingleObject(msg->StartupEvent, INFINITE);
150 CloseHandle(msg->StartupEvent);
151 return TRUE;
152 }
153
154 return FALSE;
155 }
156
157 if (pTitle)
158 SetWindowTextW(pgContext->hStatusWindow, pTitle);
159
160 SetDlgItemTextW(pgContext->hStatusWindow, IDC_STATUSLABEL, pMessage);
161
162 return TRUE;
163 }
164
165 static BOOL
166 GUIRemoveStatusMessage(
167 IN PGINA_CONTEXT pgContext)
168 {
169 if (pgContext->hStatusWindow)
170 {
171 EndDialog(pgContext->hStatusWindow, 0);
172 pgContext->hStatusWindow = NULL;
173 }
174
175 return TRUE;
176 }
177
178 static INT_PTR CALLBACK
179 EmptyWindowProc(
180 IN HWND hwndDlg,
181 IN UINT uMsg,
182 IN WPARAM wParam,
183 IN LPARAM lParam)
184 {
185 PGINA_CONTEXT pgContext;
186
187 pgContext = (PGINA_CONTEXT)GetWindowLongPtr(hwndDlg, GWL_USERDATA);
188
189 switch (uMsg)
190 {
191 case WM_INITDIALOG:
192 {
193 pgContext->hBitmap = LoadImage(hDllInstance, MAKEINTRESOURCE(IDI_ROSLOGO), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
194 }
195 case WM_PAINT:
196 {
197 PAINTSTRUCT ps;
198 HDC hdc;
199 if (pgContext->hBitmap)
200 {
201 hdc = BeginPaint(hwndDlg, &ps);
202 DrawStateW(hdc, NULL, NULL, (LPARAM)pgContext->hBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);
203 EndPaint(hwndDlg, &ps);
204 }
205 return TRUE;
206 }
207 case WM_DESTROY:
208 {
209 DeleteObject(pgContext->hBitmap);
210 return TRUE;
211 }
212 }
213 return FALSE;
214 }
215
216 static VOID
217 GUIDisplaySASNotice(
218 IN OUT PGINA_CONTEXT pgContext)
219 {
220 TRACE("GUIDisplaySASNotice()\n");
221
222 /* Display the notice window */
223 pgContext->pWlxFuncs->WlxDialogBoxParam(pgContext->hWlx,
224 pgContext->hDllInstance,
225 MAKEINTRESOURCEW(IDD_NOTICE_DLG),
226 GetDesktopWindow(),
227 EmptyWindowProc,
228 (LPARAM)NULL);
229 }
230
231 /* Get the text contained in a textbox. Allocates memory in pText
232 * to contain the text. Returns TRUE in case of success */
233 static BOOL
234 GetTextboxText(
235 IN HWND hwndDlg,
236 IN INT TextboxId,
237 OUT LPWSTR *pText)
238 {
239 LPWSTR Text;
240 int Count;
241
242 Count = GetWindowTextLength(GetDlgItem(hwndDlg, TextboxId));
243 Text = HeapAlloc(GetProcessHeap(), 0, (Count + 1) * sizeof(WCHAR));
244 if (!Text)
245 return FALSE;
246 if (Count != GetWindowTextW(GetDlgItem(hwndDlg, TextboxId), Text, Count + 1))
247 {
248 HeapFree(GetProcessHeap(), 0, Text);
249 return FALSE;
250 }
251 *pText = Text;
252 return TRUE;
253 }
254
255
256 static
257 INT
258 ResourceMessageBox(
259 IN PGINA_CONTEXT pgContext,
260 IN HWND hwnd,
261 IN UINT uType,
262 IN UINT uCaption,
263 IN UINT uText)
264 {
265 WCHAR szCaption[256];
266 WCHAR szText[256];
267
268 LoadStringW(pgContext->hDllInstance, uCaption, szCaption, 256);
269 LoadStringW(pgContext->hDllInstance, uText, szText, 256);
270
271 return pgContext->pWlxFuncs->WlxMessageBox(pgContext->hWlx,
272 hwnd,
273 szText,
274 szCaption,
275 uType);
276 }
277
278
279 static
280 BOOL
281 DoChangePassword(
282 IN PGINA_CONTEXT pgContext,
283 IN HWND hwndDlg)
284 {
285 WCHAR UserName[256];
286 WCHAR Domain[256];
287 WCHAR OldPassword[256];
288 WCHAR NewPassword1[256];
289 WCHAR NewPassword2[256];
290 PMSV1_0_CHANGEPASSWORD_REQUEST RequestBuffer = NULL;
291 PMSV1_0_CHANGEPASSWORD_RESPONSE ResponseBuffer = NULL;
292 ULONG RequestBufferSize;
293 ULONG ResponseBufferSize = 0;
294 LPWSTR Ptr;
295 BOOL res = FALSE;
296 NTSTATUS ProtocolStatus;
297 NTSTATUS Status;
298
299 GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_USERNAME, UserName, 256);
300 GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_DOMAIN, Domain, 256);
301 GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_OLDPWD, OldPassword, 256);
302 GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_NEWPWD1, NewPassword1, 256);
303 GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_NEWPWD2, NewPassword2, 256);
304
305 /* Compare the two passwords and fail if they do not match */
306 if (wcscmp(NewPassword1, NewPassword2) != 0)
307 {
308 ResourceMessageBox(pgContext,
309 hwndDlg,
310 MB_OK | MB_ICONEXCLAMATION,
311 IDS_CHANGEPWDTITLE,
312 IDS_NONMATCHINGPASSWORDS);
313 return FALSE;
314 }
315
316 /* Calculate the request buffer size */
317 RequestBufferSize = sizeof(MSV1_0_CHANGEPASSWORD_REQUEST) +
318 ((wcslen(Domain) + 1) * sizeof(WCHAR)) +
319 ((wcslen(UserName) + 1) * sizeof(WCHAR)) +
320 ((wcslen(OldPassword) + 1) * sizeof(WCHAR)) +
321 ((wcslen(NewPassword1) + 1) * sizeof(WCHAR));
322
323 /* Allocate the request buffer */
324 RequestBuffer = HeapAlloc(GetProcessHeap(),
325 HEAP_ZERO_MEMORY,
326 RequestBufferSize);
327 if (RequestBuffer == NULL)
328 {
329 ERR("HeapAlloc failed\n");
330 return FALSE;
331 }
332
333 /* Initialize the request buffer */
334 RequestBuffer->MessageType = MsV1_0ChangePassword;
335 RequestBuffer->Impersonating = TRUE;
336
337 Ptr = (LPWSTR)((ULONG_PTR)RequestBuffer + sizeof(MSV1_0_CHANGEPASSWORD_REQUEST));
338
339 /* Pack the domain name */
340 RequestBuffer->DomainName.Length = wcslen(Domain) * sizeof(WCHAR);
341 RequestBuffer->DomainName.MaximumLength = RequestBuffer->DomainName.Length + sizeof(WCHAR);
342 RequestBuffer->DomainName.Buffer = Ptr;
343
344 RtlCopyMemory(RequestBuffer->DomainName.Buffer,
345 Domain,
346 RequestBuffer->DomainName.MaximumLength);
347
348 Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->DomainName.MaximumLength);
349
350 /* Pack the user name */
351 RequestBuffer->AccountName.Length = wcslen(UserName) * sizeof(WCHAR);
352 RequestBuffer->AccountName.MaximumLength = RequestBuffer->AccountName.Length + sizeof(WCHAR);
353 RequestBuffer->AccountName.Buffer = Ptr;
354
355 RtlCopyMemory(RequestBuffer->AccountName.Buffer,
356 UserName,
357 RequestBuffer->AccountName.MaximumLength);
358
359 Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->AccountName.MaximumLength);
360
361 /* Pack the old password */
362 RequestBuffer->OldPassword.Length = wcslen(OldPassword) * sizeof(WCHAR);
363 RequestBuffer->OldPassword.MaximumLength = RequestBuffer->OldPassword.Length + sizeof(WCHAR);
364 RequestBuffer->OldPassword.Buffer = Ptr;
365
366 RtlCopyMemory(RequestBuffer->OldPassword.Buffer,
367 OldPassword,
368 RequestBuffer->OldPassword.MaximumLength);
369
370 Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->OldPassword.MaximumLength);
371
372 /* Pack the new password */
373 RequestBuffer->NewPassword.Length = wcslen(NewPassword1) * sizeof(WCHAR);
374 RequestBuffer->NewPassword.MaximumLength = RequestBuffer->NewPassword.Length + sizeof(WCHAR);
375 RequestBuffer->NewPassword.Buffer = Ptr;
376
377 RtlCopyMemory(RequestBuffer->NewPassword.Buffer,
378 NewPassword1,
379 RequestBuffer->NewPassword.MaximumLength);
380
381 /* Connect to the LSA server */
382 if (!ConnectToLsa(pgContext))
383 {
384 ERR("ConnectToLsa() failed\n");
385 goto done;
386 }
387
388 /* Call the authentication package */
389 Status = LsaCallAuthenticationPackage(pgContext->LsaHandle,
390 pgContext->AuthenticationPackage,
391 RequestBuffer,
392 RequestBufferSize,
393 (PVOID*)&ResponseBuffer,
394 &ResponseBufferSize,
395 &ProtocolStatus);
396 if (!NT_SUCCESS(Status))
397 {
398 ERR("LsaCallAuthenticationPackage failed (Status 0x%08lx)\n", Status);
399 goto done;
400 }
401
402 if (!NT_SUCCESS(ProtocolStatus))
403 {
404 TRACE("LsaCallAuthenticationPackage failed (ProtocolStatus 0x%08lx)\n", ProtocolStatus);
405 goto done;
406 }
407
408 res = TRUE;
409
410 ResourceMessageBox(pgContext,
411 hwndDlg,
412 MB_OK | MB_ICONINFORMATION,
413 IDS_CHANGEPWDTITLE,
414 IDS_PASSWORDCHANGED);
415
416 if ((wcscmp(UserName, pgContext->UserName) == 0) &&
417 (wcscmp(Domain, pgContext->Domain) == 0) &&
418 (wcscmp(OldPassword, pgContext->Password) == 0))
419 {
420 ZeroMemory(pgContext->Password, 256 * sizeof(WCHAR));
421 wcscpy(pgContext->Password, NewPassword1);
422 }
423
424 done:
425 if (RequestBuffer != NULL)
426 HeapFree(GetProcessHeap(), 0, RequestBuffer);
427
428 if (ResponseBuffer != NULL)
429 LsaFreeReturnBuffer(ResponseBuffer);
430
431 return res;
432 }
433
434
435 static INT_PTR CALLBACK
436 ChangePasswordDialogProc(
437 IN HWND hwndDlg,
438 IN UINT uMsg,
439 IN WPARAM wParam,
440 IN LPARAM lParam)
441 {
442 PGINA_CONTEXT pgContext;
443
444 pgContext = (PGINA_CONTEXT)GetWindowLongPtr(hwndDlg, GWL_USERDATA);
445
446 switch (uMsg)
447 {
448 case WM_INITDIALOG:
449 pgContext = (PGINA_CONTEXT)lParam;
450 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)pgContext);
451
452 SetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_USERNAME, pgContext->UserName);
453 SendDlgItemMessageW(hwndDlg, IDC_CHANGEPWD_DOMAIN, CB_ADDSTRING, 0, (LPARAM)pgContext->Domain);
454 SendDlgItemMessageW(hwndDlg, IDC_CHANGEPWD_DOMAIN, CB_SETCURSEL, 0, 0);
455 SetFocus(GetDlgItem(hwndDlg, IDC_CHANGEPWD_OLDPWD));
456 return TRUE;
457
458 case WM_COMMAND:
459 switch (LOWORD(wParam))
460 {
461 case IDOK:
462 if (DoChangePassword(pgContext, hwndDlg))
463 {
464 EndDialog(hwndDlg, TRUE);
465 }
466 else
467 {
468 SetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_NEWPWD1, NULL);
469 SetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_NEWPWD2, NULL);
470 SetFocus(GetDlgItem(hwndDlg, IDC_CHANGEPWD_OLDPWD));
471 }
472 return TRUE;
473
474 case IDCANCEL:
475 EndDialog(hwndDlg, FALSE);
476 return TRUE;
477 }
478 break;
479
480 case WM_CLOSE:
481 EndDialog(hwndDlg, FALSE);
482 return TRUE;
483 }
484
485 return FALSE;
486 }
487
488
489 static VOID
490 OnInitSecurityDlg(HWND hwnd,
491 PGINA_CONTEXT pgContext)
492 {
493 WCHAR Buffer1[256];
494 WCHAR Buffer2[256];
495 WCHAR Buffer3[256];
496 WCHAR Buffer4[512];
497
498 LoadStringW(pgContext->hDllInstance, IDS_LOGONMSG, Buffer1, 256);
499
500 wsprintfW(Buffer2, L"%s\\%s", pgContext->Domain, pgContext->UserName);
501 wsprintfW(Buffer4, Buffer1, Buffer2);
502
503 SetDlgItemTextW(hwnd, IDC_LOGONMSG, Buffer4);
504
505 LoadStringW(pgContext->hDllInstance, IDS_LOGONDATE, Buffer1, 256);
506
507 GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE,
508 (SYSTEMTIME*)&pgContext->LogonTime, NULL, Buffer2, 256);
509
510 GetTimeFormatW(LOCALE_USER_DEFAULT, 0,
511 (SYSTEMTIME*)&pgContext->LogonTime, NULL, Buffer3, 256);
512
513 wsprintfW(Buffer4, Buffer1, Buffer2, Buffer3);
514
515 SetDlgItemTextW(hwnd, IDC_LOGONDATE, Buffer4);
516
517 if (pgContext->bAutoAdminLogon == TRUE)
518 EnableWindow(GetDlgItem(hwnd, IDC_LOGOFF), FALSE);
519 }
520
521
522 static BOOL
523 OnChangePassword(
524 IN HWND hwnd,
525 IN PGINA_CONTEXT pgContext)
526 {
527 INT res;
528
529 TRACE("OnChangePassword()\n");
530
531 res = pgContext->pWlxFuncs->WlxDialogBoxParam(
532 pgContext->hWlx,
533 pgContext->hDllInstance,
534 MAKEINTRESOURCEW(IDD_CHANGE_PASSWORD),
535 hwnd,
536 ChangePasswordDialogProc,
537 (LPARAM)pgContext);
538
539 TRACE("Result: %x\n", res);
540
541 return FALSE;
542 }
543
544
545 static INT_PTR CALLBACK
546 LogOffDialogProc(
547 IN HWND hwndDlg,
548 IN UINT uMsg,
549 IN WPARAM wParam,
550 IN LPARAM lParam)
551 {
552 switch (uMsg)
553 {
554 case WM_INITDIALOG:
555 return TRUE;
556
557 case WM_COMMAND:
558 switch (LOWORD(wParam))
559 {
560 case IDYES:
561 EndDialog(hwndDlg, IDYES);
562 return TRUE;
563
564 case IDNO:
565 EndDialog(hwndDlg, IDNO);
566 return TRUE;
567 }
568 break;
569
570 case WM_CLOSE:
571 EndDialog(hwndDlg, IDNO);
572 return TRUE;
573 }
574
575 return FALSE;
576 }
577
578
579 static
580 INT
581 OnLogOff(
582 IN HWND hwndDlg,
583 IN PGINA_CONTEXT pgContext)
584 {
585 return pgContext->pWlxFuncs->WlxDialogBoxParam(
586 pgContext->hWlx,
587 pgContext->hDllInstance,
588 MAKEINTRESOURCEW(IDD_LOGOFF_DLG),
589 hwndDlg,
590 LogOffDialogProc,
591 (LPARAM)pgContext);
592 }
593
594
595 static INT_PTR CALLBACK
596 LoggedOnWindowProc(
597 IN HWND hwndDlg,
598 IN UINT uMsg,
599 IN WPARAM wParam,
600 IN LPARAM lParam)
601 {
602 PGINA_CONTEXT pgContext;
603
604 pgContext = (PGINA_CONTEXT)GetWindowLongPtr(hwndDlg, GWL_USERDATA);
605
606 switch (uMsg)
607 {
608 case WM_INITDIALOG:
609 {
610 pgContext = (PGINA_CONTEXT)lParam;
611 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)pgContext);
612
613 OnInitSecurityDlg(hwndDlg, (PGINA_CONTEXT)lParam);
614 SetFocus(GetDlgItem(hwndDlg, IDNO));
615 return TRUE;
616 }
617
618 case WM_COMMAND:
619 {
620 switch (LOWORD(wParam))
621 {
622 case IDC_LOCK:
623 EndDialog(hwndDlg, WLX_SAS_ACTION_LOCK_WKSTA);
624 return TRUE;
625 case IDC_LOGOFF:
626 if (OnLogOff(hwndDlg, pgContext) == IDYES)
627 EndDialog(hwndDlg, WLX_SAS_ACTION_LOGOFF);
628 return TRUE;
629 case IDC_SHUTDOWN:
630 EndDialog(hwndDlg, WLX_SAS_ACTION_SHUTDOWN_POWER_OFF);
631 return TRUE;
632 case IDC_CHANGEPWD:
633 if (OnChangePassword(hwndDlg, pgContext))
634 EndDialog(hwndDlg, WLX_SAS_ACTION_PWD_CHANGED);
635 return TRUE;
636 case IDC_TASKMGR:
637 EndDialog(hwndDlg, WLX_SAS_ACTION_TASKLIST);
638 return TRUE;
639 case IDCANCEL:
640 EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
641 return TRUE;
642 }
643 break;
644 }
645 case WM_CLOSE:
646 {
647 EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
648 return TRUE;
649 }
650 }
651
652 return FALSE;
653 }
654
655 static INT
656 GUILoggedOnSAS(
657 IN OUT PGINA_CONTEXT pgContext,
658 IN DWORD dwSasType)
659 {
660 INT result;
661
662 TRACE("GUILoggedOnSAS()\n");
663
664 if (dwSasType != WLX_SAS_TYPE_CTRL_ALT_DEL)
665 {
666 /* Nothing to do for WLX_SAS_TYPE_TIMEOUT ; the dialog will
667 * close itself thanks to the use of WlxDialogBoxParam */
668 return WLX_SAS_ACTION_NONE;
669 }
670
671 pgContext->pWlxFuncs->WlxSwitchDesktopToWinlogon(
672 pgContext->hWlx);
673
674 result = pgContext->pWlxFuncs->WlxDialogBoxParam(
675 pgContext->hWlx,
676 pgContext->hDllInstance,
677 MAKEINTRESOURCEW(IDD_LOGGEDON_DLG),
678 GetDesktopWindow(),
679 LoggedOnWindowProc,
680 (LPARAM)pgContext);
681
682 if (result < WLX_SAS_ACTION_LOGON ||
683 result > WLX_SAS_ACTION_SWITCH_CONSOLE)
684 {
685 result = WLX_SAS_ACTION_NONE;
686 }
687
688 if (result == WLX_SAS_ACTION_NONE)
689 {
690 pgContext->pWlxFuncs->WlxSwitchDesktopToUser(
691 pgContext->hWlx);
692 }
693
694 return result;
695 }
696
697 static INT_PTR CALLBACK
698 LoggedOutWindowProc(
699 IN HWND hwndDlg,
700 IN UINT uMsg,
701 IN WPARAM wParam,
702 IN LPARAM lParam)
703 {
704 PGINA_CONTEXT pgContext;
705
706 pgContext = (PGINA_CONTEXT)GetWindowLongPtr(hwndDlg, GWL_USERDATA);
707
708 switch (uMsg)
709 {
710 case WM_INITDIALOG:
711 {
712 /* FIXME: take care of NoDomainUI */
713 pgContext = (PGINA_CONTEXT)lParam;
714 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)pgContext);
715
716 if (pgContext->bDontDisplayLastUserName == FALSE)
717 SetDlgItemTextW(hwndDlg, IDC_USERNAME, pgContext->UserName);
718
719 if (pgContext->bDisableCAD == TRUE)
720 EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), FALSE);
721
722 if (pgContext->bShutdownWithoutLogon == FALSE)
723 EnableWindow(GetDlgItem(hwndDlg, IDC_SHUTDOWN), FALSE);
724
725 SendDlgItemMessageW(hwndDlg, IDC_LOGON_TO, CB_ADDSTRING, 0, (LPARAM)pgContext->Domain);
726 SendDlgItemMessageW(hwndDlg, IDC_LOGON_TO, CB_SETCURSEL, 0, 0);
727
728 SetFocus(GetDlgItem(hwndDlg, pgContext->bDontDisplayLastUserName ? IDC_USERNAME : IDC_PASSWORD));
729
730 pgContext->hBitmap = LoadImage(hDllInstance, MAKEINTRESOURCE(IDI_ROSLOGO), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
731 return TRUE;
732 }
733 case WM_PAINT:
734 {
735 PAINTSTRUCT ps;
736 HDC hdc;
737 if (pgContext->hBitmap)
738 {
739 hdc = BeginPaint(hwndDlg, &ps);
740 DrawStateW(hdc, NULL, NULL, (LPARAM)pgContext->hBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);
741 EndPaint(hwndDlg, &ps);
742 }
743 return TRUE;
744 }
745 case WM_DESTROY:
746 {
747 DeleteObject(pgContext->hBitmap);
748 return TRUE;
749 }
750 case WM_COMMAND:
751 {
752 switch (LOWORD(wParam))
753 {
754 case IDOK:
755 {
756 LPWSTR UserName = NULL, Password = NULL, Domain = NULL;
757 INT result = WLX_SAS_ACTION_NONE;
758
759 if (GetTextboxText(hwndDlg, IDC_USERNAME, &UserName) && *UserName == '\0')
760 break;
761 if (GetTextboxText(hwndDlg, IDC_LOGON_TO, &Domain) && *Domain == '\0')
762 break;
763 if (GetTextboxText(hwndDlg, IDC_PASSWORD, &Password) &&
764 DoLoginTasks(pgContext, UserName, Domain, Password))
765 {
766 ZeroMemory(pgContext->Password, 256 * sizeof(WCHAR));
767 wcscpy(pgContext->Password, Password);
768
769 result = WLX_SAS_ACTION_LOGON;
770 }
771 HeapFree(GetProcessHeap(), 0, UserName);
772 HeapFree(GetProcessHeap(), 0, Password);
773 HeapFree(GetProcessHeap(), 0, Domain);
774 EndDialog(hwndDlg, result);
775 return TRUE;
776 }
777 case IDCANCEL:
778 {
779 EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
780 return TRUE;
781 }
782 case IDC_SHUTDOWN:
783 {
784 EndDialog(hwndDlg, WLX_SAS_ACTION_SHUTDOWN);
785 return TRUE;
786 }
787 }
788 break;
789 }
790 }
791
792 return FALSE;
793 }
794
795 static INT
796 GUILoggedOutSAS(
797 IN OUT PGINA_CONTEXT pgContext)
798 {
799 int result;
800
801 TRACE("GUILoggedOutSAS()\n");
802
803 result = pgContext->pWlxFuncs->WlxDialogBoxParam(
804 pgContext->hWlx,
805 pgContext->hDllInstance,
806 MAKEINTRESOURCEW(IDD_LOGGEDOUT_DLG),
807 GetDesktopWindow(),
808 LoggedOutWindowProc,
809 (LPARAM)pgContext);
810 if (result >= WLX_SAS_ACTION_LOGON &&
811 result <= WLX_SAS_ACTION_SWITCH_CONSOLE)
812 {
813 WARN("WlxLoggedOutSAS() returns 0x%x\n", result);
814 return result;
815 }
816
817 WARN("WlxDialogBoxParam() failed (0x%x)\n", result);
818 return WLX_SAS_ACTION_NONE;
819 }
820
821
822 static VOID
823 SetLockMessage(HWND hwnd,
824 INT nDlgItem,
825 PGINA_CONTEXT pgContext)
826 {
827 WCHAR Buffer1[256];
828 WCHAR Buffer2[256];
829 WCHAR Buffer3[512];
830
831 LoadStringW(pgContext->hDllInstance, IDS_LOCKMSG, Buffer1, 256);
832
833 wsprintfW(Buffer2, L"%s\\%s", pgContext->Domain, pgContext->UserName);
834 wsprintfW(Buffer3, Buffer1, Buffer2);
835
836 SetDlgItemTextW(hwnd, nDlgItem, Buffer3);
837 }
838
839
840 static
841 BOOL
842 DoUnlock(
843 IN HWND hwndDlg,
844 IN PGINA_CONTEXT pgContext,
845 OUT LPINT Action)
846 {
847 WCHAR Buffer1[256];
848 WCHAR Buffer2[256];
849 LPWSTR UserName = NULL;
850 LPWSTR Password = NULL;
851 BOOL res = FALSE;
852
853 if (GetTextboxText(hwndDlg, IDC_USERNAME, &UserName) && *UserName == '\0')
854 return FALSE;
855
856 if (GetTextboxText(hwndDlg, IDC_PASSWORD, &Password))
857 {
858 if (UserName != NULL && Password != NULL &&
859 wcscmp(UserName, pgContext->UserName) == 0 &&
860 wcscmp(Password, pgContext->Password) == 0)
861 {
862 *Action = WLX_SAS_ACTION_UNLOCK_WKSTA;
863 res = TRUE;
864 }
865 else if (wcscmp(UserName, pgContext->UserName) == 0 &&
866 wcscmp(Password, pgContext->Password) != 0)
867 {
868 /* Wrong Password */
869 LoadStringW(pgContext->hDllInstance, IDS_LOCKEDWRONGPASSWORD, Buffer2, 256);
870 LoadStringW(pgContext->hDllInstance, IDS_COMPUTERLOCKED, Buffer1, 256);
871 MessageBoxW(hwndDlg, Buffer2, Buffer1, MB_OK | MB_ICONERROR);
872 }
873 else
874 {
875 /* Wrong user name */
876 if (DoAdminUnlock(pgContext, UserName, NULL, Password))
877 {
878 *Action = WLX_SAS_ACTION_UNLOCK_WKSTA;
879 res = TRUE;
880 }
881 else
882 {
883 LoadStringW(pgContext->hDllInstance, IDS_LOCKEDWRONGUSER, Buffer1, 256);
884 wsprintfW(Buffer2, Buffer1, pgContext->Domain, pgContext->UserName);
885 LoadStringW(pgContext->hDllInstance, IDS_COMPUTERLOCKED, Buffer1, 256);
886 MessageBoxW(hwndDlg, Buffer2, Buffer1, MB_OK | MB_ICONERROR);
887 }
888 }
889 }
890
891 if (UserName != NULL)
892 HeapFree(GetProcessHeap(), 0, UserName);
893
894 if (Password != NULL)
895 HeapFree(GetProcessHeap(), 0, Password);
896
897 return res;
898 }
899
900
901 static
902 INT_PTR
903 CALLBACK
904 UnlockWindowProc(
905 IN HWND hwndDlg,
906 IN UINT uMsg,
907 IN WPARAM wParam,
908 IN LPARAM lParam)
909 {
910 PGINA_CONTEXT pgContext;
911 INT result = WLX_SAS_ACTION_NONE;
912
913 pgContext = (PGINA_CONTEXT)GetWindowLongPtr(hwndDlg, GWL_USERDATA);
914
915 switch (uMsg)
916 {
917 case WM_INITDIALOG:
918 pgContext = (PGINA_CONTEXT)lParam;
919 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)pgContext);
920
921 SetLockMessage(hwndDlg, IDC_LOCKMSG, pgContext);
922
923 SetDlgItemTextW(hwndDlg, IDC_USERNAME, pgContext->UserName);
924 SetFocus(GetDlgItem(hwndDlg, IDC_PASSWORD));
925
926 if (pgContext->bDisableCAD == TRUE)
927 EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), FALSE);
928
929 pgContext->hBitmap = LoadImage(hDllInstance, MAKEINTRESOURCE(IDI_ROSLOGO), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
930 return TRUE;
931
932 case WM_PAINT:
933 {
934 PAINTSTRUCT ps;
935 HDC hdc;
936 if (pgContext->hBitmap)
937 {
938 hdc = BeginPaint(hwndDlg, &ps);
939 DrawStateW(hdc, NULL, NULL, (LPARAM)pgContext->hBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);
940 EndPaint(hwndDlg, &ps);
941 }
942 return TRUE;
943 }
944 case WM_DESTROY:
945 DeleteObject(pgContext->hBitmap);
946 return TRUE;
947
948 case WM_COMMAND:
949 switch (LOWORD(wParam))
950 {
951 case IDOK:
952 if (DoUnlock(hwndDlg, pgContext, &result))
953 EndDialog(hwndDlg, result);
954 return TRUE;
955
956 case IDCANCEL:
957 EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
958 return TRUE;
959 }
960 break;
961 }
962
963 return FALSE;
964 }
965
966
967 static INT
968 GUILockedSAS(
969 IN OUT PGINA_CONTEXT pgContext)
970 {
971 int result;
972
973 TRACE("GUILockedSAS()\n");
974
975 result = pgContext->pWlxFuncs->WlxDialogBoxParam(
976 pgContext->hWlx,
977 pgContext->hDllInstance,
978 MAKEINTRESOURCEW(IDD_UNLOCK_DLG),
979 GetDesktopWindow(),
980 UnlockWindowProc,
981 (LPARAM)pgContext);
982 if (result >= WLX_SAS_ACTION_LOGON &&
983 result <= WLX_SAS_ACTION_SWITCH_CONSOLE)
984 {
985 WARN("GUILockedSAS() returns 0x%x\n", result);
986 return result;
987 }
988
989 WARN("GUILockedSAS() failed (0x%x)\n", result);
990 return WLX_SAS_ACTION_NONE;
991 }
992
993
994 static INT_PTR CALLBACK
995 LockedWindowProc(
996 IN HWND hwndDlg,
997 IN UINT uMsg,
998 IN WPARAM wParam,
999 IN LPARAM lParam)
1000 {
1001 PGINA_CONTEXT pgContext;
1002
1003 pgContext = (PGINA_CONTEXT)GetWindowLongPtr(hwndDlg, GWL_USERDATA);
1004
1005 switch (uMsg)
1006 {
1007 case WM_INITDIALOG:
1008 {
1009 pgContext = (PGINA_CONTEXT)lParam;
1010 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)pgContext);
1011
1012 pgContext->hBitmap = LoadImage(hDllInstance, MAKEINTRESOURCE(IDI_ROSLOGO), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
1013 SetLockMessage(hwndDlg, IDC_LOCKMSG, pgContext);
1014 return TRUE;
1015 }
1016 case WM_PAINT:
1017 {
1018 PAINTSTRUCT ps;
1019 HDC hdc;
1020 if (pgContext->hBitmap)
1021 {
1022 hdc = BeginPaint(hwndDlg, &ps);
1023 DrawStateW(hdc, NULL, NULL, (LPARAM)pgContext->hBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);
1024 EndPaint(hwndDlg, &ps);
1025 }
1026 return TRUE;
1027 }
1028 case WM_DESTROY:
1029 {
1030 DeleteObject(pgContext->hBitmap);
1031 return TRUE;
1032 }
1033 }
1034
1035 return FALSE;
1036 }
1037
1038
1039 static VOID
1040 GUIDisplayLockedNotice(
1041 IN OUT PGINA_CONTEXT pgContext)
1042 {
1043 TRACE("GUIdisplayLockedNotice()\n");
1044
1045 pgContext->pWlxFuncs->WlxDialogBoxParam(
1046 pgContext->hWlx,
1047 pgContext->hDllInstance,
1048 MAKEINTRESOURCEW(IDD_LOCKED_DLG),
1049 GetDesktopWindow(),
1050 LockedWindowProc,
1051 (LPARAM)pgContext);
1052 }
1053
1054 GINA_UI GinaGraphicalUI = {
1055 GUIInitialize,
1056 GUIDisplayStatusMessage,
1057 GUIRemoveStatusMessage,
1058 GUIDisplaySASNotice,
1059 GUILoggedOnSAS,
1060 GUILoggedOutSAS,
1061 GUILockedSAS,
1062 GUIDisplayLockedNotice,
1063 };