[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
224 INT
225 ResourceMessageBox(
226 IN PGINA_CONTEXT pgContext,
227 IN HWND hwnd,
228 IN UINT uType,
229 IN UINT uCaption,
230 IN UINT uText)
231 {
232 WCHAR szCaption[256];
233 WCHAR szText[256];
234
235 LoadStringW(pgContext->hDllInstance, uCaption, szCaption, 256);
236 LoadStringW(pgContext->hDllInstance, uText, szText, 256);
237
238 return pgContext->pWlxFuncs->WlxMessageBox(pgContext->hWlx,
239 hwnd,
240 szText,
241 szCaption,
242 uType);
243 }
244
245
246 static
247 BOOL
248 DoChangePassword(
249 IN PGINA_CONTEXT pgContext,
250 IN HWND hwndDlg)
251 {
252 WCHAR UserName[256];
253 WCHAR DomainName[256];
254 WCHAR OldPassword[256];
255 WCHAR NewPassword1[256];
256 WCHAR NewPassword2[256];
257 PMSV1_0_CHANGEPASSWORD_REQUEST RequestBuffer = NULL;
258 PMSV1_0_CHANGEPASSWORD_RESPONSE ResponseBuffer = NULL;
259 ULONG RequestBufferSize;
260 ULONG ResponseBufferSize = 0;
261 LPWSTR Ptr;
262 BOOL res = FALSE;
263 NTSTATUS ProtocolStatus;
264 NTSTATUS Status;
265
266 GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_USERNAME, UserName, 256);
267 GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_DOMAIN, DomainName, 256);
268 GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_OLDPWD, OldPassword, 256);
269 GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_NEWPWD1, NewPassword1, 256);
270 GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_NEWPWD2, NewPassword2, 256);
271
272 /* Compare the two passwords and fail if they do not match */
273 if (wcscmp(NewPassword1, NewPassword2) != 0)
274 {
275 ResourceMessageBox(pgContext,
276 hwndDlg,
277 MB_OK | MB_ICONEXCLAMATION,
278 IDS_CHANGEPWDTITLE,
279 IDS_NONMATCHINGPASSWORDS);
280 return FALSE;
281 }
282
283 /* Calculate the request buffer size */
284 RequestBufferSize = sizeof(MSV1_0_CHANGEPASSWORD_REQUEST) +
285 ((wcslen(DomainName) + 1) * sizeof(WCHAR)) +
286 ((wcslen(UserName) + 1) * sizeof(WCHAR)) +
287 ((wcslen(OldPassword) + 1) * sizeof(WCHAR)) +
288 ((wcslen(NewPassword1) + 1) * sizeof(WCHAR));
289
290 /* Allocate the request buffer */
291 RequestBuffer = HeapAlloc(GetProcessHeap(),
292 HEAP_ZERO_MEMORY,
293 RequestBufferSize);
294 if (RequestBuffer == NULL)
295 {
296 ERR("HeapAlloc failed\n");
297 return FALSE;
298 }
299
300 /* Initialize the request buffer */
301 RequestBuffer->MessageType = MsV1_0ChangePassword;
302 RequestBuffer->Impersonating = TRUE;
303
304 Ptr = (LPWSTR)((ULONG_PTR)RequestBuffer + sizeof(MSV1_0_CHANGEPASSWORD_REQUEST));
305
306 /* Pack the domain name */
307 RequestBuffer->DomainName.Length = wcslen(DomainName) * sizeof(WCHAR);
308 RequestBuffer->DomainName.MaximumLength = RequestBuffer->DomainName.Length + sizeof(WCHAR);
309 RequestBuffer->DomainName.Buffer = Ptr;
310
311 RtlCopyMemory(RequestBuffer->DomainName.Buffer,
312 DomainName,
313 RequestBuffer->DomainName.MaximumLength);
314
315 Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->DomainName.MaximumLength);
316
317 /* Pack the user name */
318 RequestBuffer->AccountName.Length = wcslen(UserName) * sizeof(WCHAR);
319 RequestBuffer->AccountName.MaximumLength = RequestBuffer->AccountName.Length + sizeof(WCHAR);
320 RequestBuffer->AccountName.Buffer = Ptr;
321
322 RtlCopyMemory(RequestBuffer->AccountName.Buffer,
323 UserName,
324 RequestBuffer->AccountName.MaximumLength);
325
326 Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->AccountName.MaximumLength);
327
328 /* Pack the old password */
329 RequestBuffer->OldPassword.Length = wcslen(OldPassword) * sizeof(WCHAR);
330 RequestBuffer->OldPassword.MaximumLength = RequestBuffer->OldPassword.Length + sizeof(WCHAR);
331 RequestBuffer->OldPassword.Buffer = Ptr;
332
333 RtlCopyMemory(RequestBuffer->OldPassword.Buffer,
334 OldPassword,
335 RequestBuffer->OldPassword.MaximumLength);
336
337 Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->OldPassword.MaximumLength);
338
339 /* Pack the new password */
340 RequestBuffer->NewPassword.Length = wcslen(NewPassword1) * sizeof(WCHAR);
341 RequestBuffer->NewPassword.MaximumLength = RequestBuffer->NewPassword.Length + sizeof(WCHAR);
342 RequestBuffer->NewPassword.Buffer = Ptr;
343
344 RtlCopyMemory(RequestBuffer->NewPassword.Buffer,
345 NewPassword1,
346 RequestBuffer->NewPassword.MaximumLength);
347
348 /* Connect to the LSA server */
349 if (!ConnectToLsa(pgContext))
350 {
351 ERR("ConnectToLsa() failed\n");
352 return FALSE;
353 }
354
355 /* Call the authentication package */
356 Status = LsaCallAuthenticationPackage(pgContext->LsaHandle,
357 pgContext->AuthenticationPackage,
358 RequestBuffer,
359 RequestBufferSize,
360 (PVOID*)&ResponseBuffer,
361 &ResponseBufferSize,
362 &ProtocolStatus);
363 if (!NT_SUCCESS(Status))
364 {
365 ERR("LsaCallAuthenticationPackage failed (Status 0x%08lx)\n", Status);
366 goto done;
367 }
368
369 if (!NT_SUCCESS(ProtocolStatus))
370 {
371 TRACE("LsaCallAuthenticationPackage failed (ProtocolStatus 0x%08lx)\n", ProtocolStatus);
372 goto done;
373 }
374
375 res = TRUE;
376
377 ResourceMessageBox(pgContext,
378 hwndDlg,
379 MB_OK | MB_ICONINFORMATION,
380 IDS_CHANGEPWDTITLE,
381 IDS_PASSWORDCHANGED);
382
383 done:
384 if (RequestBuffer != NULL)
385 HeapFree(GetProcessHeap(), 0, RequestBuffer);
386
387 if (ResponseBuffer != NULL)
388 LsaFreeReturnBuffer(ResponseBuffer);
389
390 return res;
391 }
392
393
394 static INT_PTR CALLBACK
395 ChangePasswordDialogProc(
396 IN HWND hwndDlg,
397 IN UINT uMsg,
398 IN WPARAM wParam,
399 IN LPARAM lParam)
400 {
401 PGINA_CONTEXT pgContext;
402
403 pgContext = (PGINA_CONTEXT)GetWindowLongPtr(hwndDlg, GWL_USERDATA);
404
405 switch (uMsg)
406 {
407 case WM_INITDIALOG:
408 pgContext = (PGINA_CONTEXT)lParam;
409 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)pgContext);
410
411 SetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_USERNAME, pgContext->UserName);
412 SendDlgItemMessageW(hwndDlg, IDC_CHANGEPWD_DOMAIN, CB_ADDSTRING, 0, (LPARAM)pgContext->Domain);
413 SendDlgItemMessageW(hwndDlg, IDC_CHANGEPWD_DOMAIN, CB_SETCURSEL, 0, 0);
414 SetFocus(GetDlgItem(hwndDlg, IDC_CHANGEPWD_OLDPWD));
415 return TRUE;
416
417 case WM_COMMAND:
418 switch (LOWORD(wParam))
419 {
420 case IDOK:
421 if (DoChangePassword(pgContext, hwndDlg))
422 {
423 EndDialog(hwndDlg, TRUE);
424 }
425 else
426 {
427 SetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_NEWPWD1, NULL);
428 SetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_NEWPWD2, NULL);
429 SetFocus(GetDlgItem(hwndDlg, IDC_CHANGEPWD_OLDPWD));
430 }
431 return TRUE;
432
433 case IDCANCEL:
434 EndDialog(hwndDlg, FALSE);
435 return TRUE;
436 }
437 break;
438
439 case WM_CLOSE:
440 EndDialog(hwndDlg, FALSE);
441 return TRUE;
442 }
443
444 return FALSE;
445 }
446
447
448 static VOID
449 OnInitSecurityDlg(HWND hwnd,
450 PGINA_CONTEXT pgContext)
451 {
452 WCHAR Buffer1[256];
453 WCHAR Buffer2[256];
454 WCHAR Buffer3[256];
455 WCHAR Buffer4[512];
456
457 LoadStringW(pgContext->hDllInstance, IDS_LOGONMSG, Buffer1, 256);
458
459 wsprintfW(Buffer2, L"%s\\%s", pgContext->Domain, pgContext->UserName);
460 wsprintfW(Buffer4, Buffer1, Buffer2);
461
462 SetDlgItemTextW(hwnd, IDC_LOGONMSG, Buffer4);
463
464 LoadStringW(pgContext->hDllInstance, IDS_LOGONDATE, Buffer1, 256);
465
466 GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE,
467 (SYSTEMTIME*)&pgContext->LogonTime, NULL, Buffer2, 256);
468
469 GetTimeFormatW(LOCALE_USER_DEFAULT, 0,
470 (SYSTEMTIME*)&pgContext->LogonTime, NULL, Buffer3, 256);
471
472 wsprintfW(Buffer4, Buffer1, Buffer2, Buffer3);
473
474 SetDlgItemTextW(hwnd, IDC_LOGONDATE, Buffer4);
475
476 if (pgContext->bAutoAdminLogon == TRUE)
477 EnableWindow(GetDlgItem(hwnd, IDC_LOGOFF), FALSE);
478 }
479
480
481 static BOOL
482 OnChangePassword(
483 IN HWND hwnd,
484 IN PGINA_CONTEXT pgContext)
485 {
486 INT res;
487
488 TRACE("OnChangePassword()\n");
489
490 res = pgContext->pWlxFuncs->WlxDialogBoxParam(
491 pgContext->hWlx,
492 pgContext->hDllInstance,
493 MAKEINTRESOURCEW(IDD_CHANGE_PASSWORD),
494 hwnd,
495 ChangePasswordDialogProc,
496 (LPARAM)pgContext);
497
498 TRACE("Result: %x\n", res);
499
500 return FALSE;
501 }
502
503
504 static INT_PTR CALLBACK
505 LogOffDialogProc(
506 IN HWND hwndDlg,
507 IN UINT uMsg,
508 IN WPARAM wParam,
509 IN LPARAM lParam)
510 {
511 switch (uMsg)
512 {
513 case WM_INITDIALOG:
514 return TRUE;
515
516 case WM_COMMAND:
517 switch (LOWORD(wParam))
518 {
519 case IDYES:
520 EndDialog(hwndDlg, IDYES);
521 return TRUE;
522
523 case IDNO:
524 EndDialog(hwndDlg, IDNO);
525 return TRUE;
526 }
527 break;
528
529 case WM_CLOSE:
530 EndDialog(hwndDlg, IDNO);
531 return TRUE;
532 }
533
534 return FALSE;
535 }
536
537
538 static
539 INT
540 OnLogOff(
541 IN HWND hwndDlg,
542 IN PGINA_CONTEXT pgContext)
543 {
544 return pgContext->pWlxFuncs->WlxDialogBoxParam(
545 pgContext->hWlx,
546 pgContext->hDllInstance,
547 MAKEINTRESOURCEW(IDD_LOGOFF_DLG),
548 hwndDlg,
549 LogOffDialogProc,
550 (LPARAM)pgContext);
551 }
552
553
554 static INT_PTR CALLBACK
555 LoggedOnWindowProc(
556 IN HWND hwndDlg,
557 IN UINT uMsg,
558 IN WPARAM wParam,
559 IN LPARAM lParam)
560 {
561 PGINA_CONTEXT pgContext;
562
563 pgContext = (PGINA_CONTEXT)GetWindowLongPtr(hwndDlg, GWL_USERDATA);
564
565 switch (uMsg)
566 {
567 case WM_INITDIALOG:
568 {
569 pgContext = (PGINA_CONTEXT)lParam;
570 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)pgContext);
571
572 OnInitSecurityDlg(hwndDlg, (PGINA_CONTEXT)lParam);
573 SetFocus(GetDlgItem(hwndDlg, IDNO));
574 return TRUE;
575 }
576
577 case WM_COMMAND:
578 {
579 switch (LOWORD(wParam))
580 {
581 case IDC_LOCK:
582 EndDialog(hwndDlg, WLX_SAS_ACTION_LOCK_WKSTA);
583 return TRUE;
584 case IDC_LOGOFF:
585 if (OnLogOff(hwndDlg, pgContext) == IDYES)
586 EndDialog(hwndDlg, WLX_SAS_ACTION_LOGOFF);
587 return TRUE;
588 case IDC_SHUTDOWN:
589 EndDialog(hwndDlg, WLX_SAS_ACTION_SHUTDOWN_POWER_OFF);
590 return TRUE;
591 case IDC_CHANGEPWD:
592 if (OnChangePassword(hwndDlg, pgContext))
593 EndDialog(hwndDlg, WLX_SAS_ACTION_PWD_CHANGED);
594 return TRUE;
595 case IDC_TASKMGR:
596 EndDialog(hwndDlg, WLX_SAS_ACTION_TASKLIST);
597 return TRUE;
598 case IDCANCEL:
599 EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
600 return TRUE;
601 }
602 break;
603 }
604 case WM_CLOSE:
605 {
606 EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
607 return TRUE;
608 }
609 }
610
611 return FALSE;
612 }
613
614 static INT
615 GUILoggedOnSAS(
616 IN OUT PGINA_CONTEXT pgContext,
617 IN DWORD dwSasType)
618 {
619 INT result;
620
621 TRACE("GUILoggedOnSAS()\n");
622
623 if (dwSasType != WLX_SAS_TYPE_CTRL_ALT_DEL)
624 {
625 /* Nothing to do for WLX_SAS_TYPE_TIMEOUT ; the dialog will
626 * close itself thanks to the use of WlxDialogBoxParam */
627 return WLX_SAS_ACTION_NONE;
628 }
629
630 pgContext->pWlxFuncs->WlxSwitchDesktopToWinlogon(
631 pgContext->hWlx);
632
633 result = pgContext->pWlxFuncs->WlxDialogBoxParam(
634 pgContext->hWlx,
635 pgContext->hDllInstance,
636 MAKEINTRESOURCEW(IDD_LOGGEDON_DLG),
637 GetDesktopWindow(),
638 LoggedOnWindowProc,
639 (LPARAM)pgContext);
640
641 if (result < WLX_SAS_ACTION_LOGON ||
642 result > WLX_SAS_ACTION_SWITCH_CONSOLE)
643 {
644 result = WLX_SAS_ACTION_NONE;
645 }
646
647 if (result == WLX_SAS_ACTION_NONE)
648 {
649 pgContext->pWlxFuncs->WlxSwitchDesktopToUser(
650 pgContext->hWlx);
651 }
652
653 return result;
654 }
655
656 static INT_PTR CALLBACK
657 LoggedOutWindowProc(
658 IN HWND hwndDlg,
659 IN UINT uMsg,
660 IN WPARAM wParam,
661 IN LPARAM lParam)
662 {
663 PGINA_CONTEXT pgContext;
664
665 pgContext = (PGINA_CONTEXT)GetWindowLongPtr(hwndDlg, GWL_USERDATA);
666
667 switch (uMsg)
668 {
669 case WM_INITDIALOG:
670 {
671 /* FIXME: take care of NoDomainUI */
672 pgContext = (PGINA_CONTEXT)lParam;
673 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)pgContext);
674
675 if (pgContext->bDontDisplayLastUserName == FALSE)
676 SetDlgItemTextW(hwndDlg, IDC_USERNAME, pgContext->UserName);
677
678 if (pgContext->bDisableCAD == TRUE)
679 EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), FALSE);
680
681 if (pgContext->bShutdownWithoutLogon == FALSE)
682 EnableWindow(GetDlgItem(hwndDlg, IDC_SHUTDOWN), FALSE);
683
684 SetFocus(GetDlgItem(hwndDlg, pgContext->bDontDisplayLastUserName ? IDC_USERNAME : IDC_PASSWORD));
685
686 pgContext->hBitmap = LoadImage(hDllInstance, MAKEINTRESOURCE(IDI_ROSLOGO), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
687 return TRUE;
688 }
689 case WM_PAINT:
690 {
691 PAINTSTRUCT ps;
692 HDC hdc;
693 if (pgContext->hBitmap)
694 {
695 hdc = BeginPaint(hwndDlg, &ps);
696 DrawStateW(hdc, NULL, NULL, (LPARAM)pgContext->hBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);
697 EndPaint(hwndDlg, &ps);
698 }
699 return TRUE;
700 }
701 case WM_DESTROY:
702 {
703 DeleteObject(pgContext->hBitmap);
704 return TRUE;
705 }
706 case WM_COMMAND:
707 {
708 switch (LOWORD(wParam))
709 {
710 case IDOK:
711 {
712 LPWSTR UserName = NULL, Password = NULL;
713 INT result = WLX_SAS_ACTION_NONE;
714
715 if (GetTextboxText(hwndDlg, IDC_USERNAME, &UserName) && *UserName == '\0')
716 break;
717 if (GetTextboxText(hwndDlg, IDC_PASSWORD, &Password) &&
718 DoLoginTasks(pgContext, UserName, NULL, Password))
719 {
720 pgContext->Password = HeapAlloc(GetProcessHeap(),
721 HEAP_ZERO_MEMORY,
722 (wcslen(Password) + 1) * sizeof(WCHAR));
723 if (pgContext->Password != NULL)
724 wcscpy(pgContext->Password, Password);
725
726 result = WLX_SAS_ACTION_LOGON;
727 }
728 HeapFree(GetProcessHeap(), 0, UserName);
729 HeapFree(GetProcessHeap(), 0, Password);
730 EndDialog(hwndDlg, result);
731 return TRUE;
732 }
733 case IDCANCEL:
734 {
735 EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
736 return TRUE;
737 }
738 case IDC_SHUTDOWN:
739 {
740 EndDialog(hwndDlg, WLX_SAS_ACTION_SHUTDOWN);
741 return TRUE;
742 }
743 }
744 break;
745 }
746 }
747
748 return FALSE;
749 }
750
751 static INT
752 GUILoggedOutSAS(
753 IN OUT PGINA_CONTEXT pgContext)
754 {
755 int result;
756
757 TRACE("GUILoggedOutSAS()\n");
758
759 result = pgContext->pWlxFuncs->WlxDialogBoxParam(
760 pgContext->hWlx,
761 pgContext->hDllInstance,
762 MAKEINTRESOURCEW(IDD_LOGGEDOUT_DLG),
763 GetDesktopWindow(),
764 LoggedOutWindowProc,
765 (LPARAM)pgContext);
766 if (result >= WLX_SAS_ACTION_LOGON &&
767 result <= WLX_SAS_ACTION_SWITCH_CONSOLE)
768 {
769 WARN("WlxLoggedOutSAS() returns 0x%x\n", result);
770 return result;
771 }
772
773 WARN("WlxDialogBoxParam() failed (0x%x)\n", result);
774 return WLX_SAS_ACTION_NONE;
775 }
776
777
778 static VOID
779 SetLockMessage(HWND hwnd,
780 INT nDlgItem,
781 PGINA_CONTEXT pgContext)
782 {
783 WCHAR Buffer1[256];
784 WCHAR Buffer2[256];
785 WCHAR Buffer3[512];
786
787 LoadStringW(pgContext->hDllInstance, IDS_LOCKMSG, Buffer1, 256);
788
789 wsprintfW(Buffer2, L"%s\\%s", pgContext->Domain, pgContext->UserName);
790 wsprintfW(Buffer3, Buffer1, Buffer2);
791
792 SetDlgItemTextW(hwnd, nDlgItem, Buffer3);
793 }
794
795
796 static
797 BOOL
798 DoUnlock(
799 IN HWND hwndDlg,
800 IN PGINA_CONTEXT pgContext,
801 OUT LPINT Action)
802 {
803 WCHAR Buffer1[256];
804 WCHAR Buffer2[256];
805 LPWSTR UserName = NULL;
806 LPWSTR Password = NULL;
807 BOOL res = FALSE;
808
809 if (GetTextboxText(hwndDlg, IDC_USERNAME, &UserName) && *UserName == '\0')
810 return FALSE;
811
812 if (GetTextboxText(hwndDlg, IDC_PASSWORD, &Password))
813 {
814 if (UserName != NULL && Password != NULL &&
815 wcscmp(UserName, pgContext->UserName) == 0 &&
816 wcscmp(Password, pgContext->Password) == 0)
817 {
818 *Action = WLX_SAS_ACTION_UNLOCK_WKSTA;
819 res = TRUE;
820 }
821 else if (wcscmp(UserName, pgContext->UserName) == 0 &&
822 wcscmp(Password, pgContext->Password) != 0)
823 {
824 /* Wrong Password */
825 LoadStringW(pgContext->hDllInstance, IDS_LOCKEDWRONGPASSWORD, Buffer2, 256);
826 LoadStringW(pgContext->hDllInstance, IDS_COMPUTERLOCKED, Buffer1, 256);
827 MessageBoxW(hwndDlg, Buffer2, Buffer1, MB_OK | MB_ICONERROR);
828 }
829 else
830 {
831 /* Wrong user name */
832 if (DoAdminUnlock(UserName, NULL, Password))
833 {
834 *Action = WLX_SAS_ACTION_UNLOCK_WKSTA;
835 res = TRUE;
836 }
837 else
838 {
839 LoadStringW(pgContext->hDllInstance, IDS_LOCKEDWRONGUSER, Buffer1, 256);
840 wsprintfW(Buffer2, Buffer1, pgContext->Domain, pgContext->UserName);
841 LoadStringW(pgContext->hDllInstance, IDS_COMPUTERLOCKED, Buffer1, 256);
842 MessageBoxW(hwndDlg, Buffer2, Buffer1, MB_OK | MB_ICONERROR);
843 }
844 }
845 }
846
847 if (UserName != NULL)
848 HeapFree(GetProcessHeap(), 0, UserName);
849
850 if (Password != NULL)
851 HeapFree(GetProcessHeap(), 0, Password);
852
853 return res;
854 }
855
856
857 static
858 INT_PTR
859 CALLBACK
860 UnlockWindowProc(
861 IN HWND hwndDlg,
862 IN UINT uMsg,
863 IN WPARAM wParam,
864 IN LPARAM lParam)
865 {
866 PGINA_CONTEXT pgContext;
867 INT result = WLX_SAS_ACTION_NONE;
868
869 pgContext = (PGINA_CONTEXT)GetWindowLongPtr(hwndDlg, GWL_USERDATA);
870
871 switch (uMsg)
872 {
873 case WM_INITDIALOG:
874 pgContext = (PGINA_CONTEXT)lParam;
875 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)pgContext);
876
877 SetLockMessage(hwndDlg, IDC_LOCKMSG, pgContext);
878
879 SetDlgItemTextW(hwndDlg, IDC_USERNAME, pgContext->UserName);
880 SetFocus(GetDlgItem(hwndDlg, IDC_PASSWORD));
881
882 if (pgContext->bDisableCAD == TRUE)
883 EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), FALSE);
884
885 pgContext->hBitmap = LoadImage(hDllInstance, MAKEINTRESOURCE(IDI_ROSLOGO), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
886 return TRUE;
887
888 case WM_PAINT:
889 {
890 PAINTSTRUCT ps;
891 HDC hdc;
892 if (pgContext->hBitmap)
893 {
894 hdc = BeginPaint(hwndDlg, &ps);
895 DrawStateW(hdc, NULL, NULL, (LPARAM)pgContext->hBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);
896 EndPaint(hwndDlg, &ps);
897 }
898 return TRUE;
899 }
900 case WM_DESTROY:
901 DeleteObject(pgContext->hBitmap);
902 return TRUE;
903
904 case WM_COMMAND:
905 switch (LOWORD(wParam))
906 {
907 case IDOK:
908 if (DoUnlock(hwndDlg, pgContext, &result))
909 EndDialog(hwndDlg, result);
910 return TRUE;
911
912 case IDCANCEL:
913 EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
914 return TRUE;
915 }
916 break;
917 }
918
919 return FALSE;
920 }
921
922
923 static INT
924 GUILockedSAS(
925 IN OUT PGINA_CONTEXT pgContext)
926 {
927 int result;
928
929 TRACE("GUILockedSAS()\n");
930
931 result = pgContext->pWlxFuncs->WlxDialogBoxParam(
932 pgContext->hWlx,
933 pgContext->hDllInstance,
934 MAKEINTRESOURCEW(IDD_UNLOCK_DLG),
935 GetDesktopWindow(),
936 UnlockWindowProc,
937 (LPARAM)pgContext);
938 if (result >= WLX_SAS_ACTION_LOGON &&
939 result <= WLX_SAS_ACTION_SWITCH_CONSOLE)
940 {
941 WARN("GUILockedSAS() returns 0x%x\n", result);
942 return result;
943 }
944
945 WARN("GUILockedSAS() failed (0x%x)\n", result);
946 return WLX_SAS_ACTION_NONE;
947 }
948
949
950 static INT_PTR CALLBACK
951 LockedWindowProc(
952 IN HWND hwndDlg,
953 IN UINT uMsg,
954 IN WPARAM wParam,
955 IN LPARAM lParam)
956 {
957 PGINA_CONTEXT pgContext;
958
959 pgContext = (PGINA_CONTEXT)GetWindowLongPtr(hwndDlg, GWL_USERDATA);
960
961 switch (uMsg)
962 {
963 case WM_INITDIALOG:
964 {
965 pgContext = (PGINA_CONTEXT)lParam;
966 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)pgContext);
967
968 pgContext->hBitmap = LoadImage(hDllInstance, MAKEINTRESOURCE(IDI_ROSLOGO), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
969 SetLockMessage(hwndDlg, IDC_LOCKMSG, pgContext);
970 return TRUE;
971 }
972 case WM_PAINT:
973 {
974 PAINTSTRUCT ps;
975 HDC hdc;
976 if (pgContext->hBitmap)
977 {
978 hdc = BeginPaint(hwndDlg, &ps);
979 DrawStateW(hdc, NULL, NULL, (LPARAM)pgContext->hBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);
980 EndPaint(hwndDlg, &ps);
981 }
982 return TRUE;
983 }
984 case WM_DESTROY:
985 {
986 DeleteObject(pgContext->hBitmap);
987 return TRUE;
988 }
989 }
990
991 return FALSE;
992 }
993
994
995 static VOID
996 GUIDisplayLockedNotice(
997 IN OUT PGINA_CONTEXT pgContext)
998 {
999 TRACE("GUIdisplayLockedNotice()\n");
1000
1001 pgContext->pWlxFuncs->WlxDialogBoxParam(
1002 pgContext->hWlx,
1003 pgContext->hDllInstance,
1004 MAKEINTRESOURCEW(IDD_LOCKED_DLG),
1005 GetDesktopWindow(),
1006 LockedWindowProc,
1007 (LPARAM)pgContext);
1008 }
1009
1010 GINA_UI GinaGraphicalUI = {
1011 GUIInitialize,
1012 GUIDisplayStatusMessage,
1013 GUIRemoveStatusMessage,
1014 GUIDisplaySASNotice,
1015 GUILoggedOnSAS,
1016 GUILoggedOutSAS,
1017 GUILockedSAS,
1018 GUIDisplayLockedNotice,
1019 };