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