[WINLOGON][MSGINA] Fix typo.
[reactos.git] / 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 #include <winreg.h>
13
14 typedef struct _DISPLAYSTATUSMSG
15 {
16 PGINA_CONTEXT Context;
17 HDESK hDesktop;
18 DWORD dwOptions;
19 PWSTR pTitle;
20 PWSTR pMessage;
21 HANDLE StartupEvent;
22 } DISPLAYSTATUSMSG, *PDISPLAYSTATUSMSG;
23
24 typedef struct _LEGALNOTICEDATA
25 {
26 LPWSTR pszCaption;
27 LPWSTR pszText;
28 } LEGALNOTICEDATA, *PLEGALNOTICEDATA;
29
30 typedef struct _DLG_DATA
31 {
32 PGINA_CONTEXT pgContext;
33 HBITMAP hBitmap;
34 } DLG_DATA, *PDLG_DATA;
35
36 static BOOL
37 GUIInitialize(
38 IN OUT PGINA_CONTEXT pgContext)
39 {
40 TRACE("GUIInitialize(%p)\n", pgContext);
41 return TRUE;
42 }
43
44
45 static
46 VOID
47 SetWelcomeText(HWND hWnd)
48 {
49 PWCHAR pBuffer = NULL, p;
50 HKEY hKey;
51 DWORD BufSize, dwType, dwWelcomeSize, dwTitleLength;
52 LONG rc;
53
54 TRACE("SetWelcomeText(%p)\n", hWnd);
55
56 /* Open the Winlogon key */
57 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
58 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
59 0,
60 KEY_QUERY_VALUE,
61 &hKey);
62 if (rc != ERROR_SUCCESS)
63 {
64 WARN("RegOpenKeyExW() failed with error %lu\n", rc);
65 return;
66 }
67
68 /* Get the size of the Welcome value */
69 dwWelcomeSize = 0;
70 rc = RegQueryValueExW(hKey,
71 L"Welcome",
72 NULL,
73 &dwType,
74 NULL,
75 &dwWelcomeSize);
76 if (rc == ERROR_FILE_NOT_FOUND || dwWelcomeSize == 0 || dwType != REG_SZ)
77 goto done;
78
79 dwTitleLength = GetWindowTextLengthW(hWnd);
80 BufSize = dwWelcomeSize + ((dwTitleLength + 1) * sizeof(WCHAR));
81
82 pBuffer = HeapAlloc(GetProcessHeap(), 0, BufSize);
83 if (pBuffer == NULL)
84 goto done;
85
86 GetWindowTextW(hWnd, pBuffer, BufSize / sizeof(WCHAR));
87 wcscat(pBuffer, L" ");
88 p = &pBuffer[dwTitleLength + 1];
89
90 RegQueryValueExW(hKey,
91 L"Welcome",
92 NULL,
93 &dwType,
94 (PBYTE)p,
95 &dwWelcomeSize);
96
97 SetWindowText(hWnd, pBuffer);
98
99 done:
100 if (pBuffer != NULL)
101 HeapFree(GetProcessHeap(), 0, pBuffer);
102
103 RegCloseKey(hKey);
104 }
105
106
107 static INT_PTR CALLBACK
108 StatusDialogProc(
109 IN HWND hwndDlg,
110 IN UINT uMsg,
111 IN WPARAM wParam,
112 IN LPARAM lParam)
113 {
114 UNREFERENCED_PARAMETER(wParam);
115
116 switch (uMsg)
117 {
118 case WM_INITDIALOG:
119 {
120 PDISPLAYSTATUSMSG msg = (PDISPLAYSTATUSMSG)lParam;
121 if (!msg)
122 return FALSE;
123
124 msg->Context->hStatusWindow = hwndDlg;
125
126 if (msg->pTitle)
127 SetWindowTextW(hwndDlg, msg->pTitle);
128 SetDlgItemTextW(hwndDlg, IDC_STATUS_MESSAGE, msg->pMessage);
129 SetEvent(msg->StartupEvent);
130 return TRUE;
131 }
132 }
133 return FALSE;
134 }
135
136 static DWORD WINAPI
137 StartupWindowThread(LPVOID lpParam)
138 {
139 HDESK hDesk;
140 PDISPLAYSTATUSMSG msg = (PDISPLAYSTATUSMSG)lpParam;
141
142 /* When SetThreadDesktop is called the system closes the desktop handle when needed
143 so we have to create a new handle because this handle may still be in use by winlogon */
144 if (!DuplicateHandle ( GetCurrentProcess(),
145 msg->hDesktop,
146 GetCurrentProcess(),
147 (HANDLE*)&hDesk,
148 0,
149 FALSE,
150 DUPLICATE_SAME_ACCESS))
151 {
152 ERR("Duplicating handle failed!\n");
153 HeapFree(GetProcessHeap(), 0, lpParam);
154 return FALSE;
155 }
156
157 if(!SetThreadDesktop(hDesk))
158 {
159 ERR("Setting thread desktop failed!\n");
160 HeapFree(GetProcessHeap(), 0, lpParam);
161 return FALSE;
162 }
163
164 DialogBoxParamW(
165 hDllInstance,
166 MAKEINTRESOURCEW(IDD_STATUS),
167 GetDesktopWindow(),
168 StatusDialogProc,
169 (LPARAM)lpParam);
170
171 HeapFree(GetProcessHeap(), 0, lpParam);
172 return TRUE;
173 }
174
175 static BOOL
176 GUIDisplayStatusMessage(
177 IN PGINA_CONTEXT pgContext,
178 IN HDESK hDesktop,
179 IN DWORD dwOptions,
180 IN PWSTR pTitle,
181 IN PWSTR pMessage)
182 {
183 PDISPLAYSTATUSMSG msg;
184 HANDLE Thread;
185 DWORD ThreadId;
186
187 TRACE("GUIDisplayStatusMessage(%ws)\n", pMessage);
188
189 if (!pgContext->hStatusWindow)
190 {
191 /*
192 * If everything goes correctly, 'msg' is freed
193 * by the 'StartupWindowThread' thread.
194 */
195 msg = (PDISPLAYSTATUSMSG)HeapAlloc(GetProcessHeap(),
196 HEAP_ZERO_MEMORY,
197 sizeof(*msg));
198 if(!msg)
199 return FALSE;
200
201 msg->Context = pgContext;
202 msg->dwOptions = dwOptions;
203 msg->pTitle = pTitle;
204 msg->pMessage = pMessage;
205 msg->hDesktop = hDesktop;
206
207 msg->StartupEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
208
209 if (!msg->StartupEvent)
210 {
211 HeapFree(GetProcessHeap(), 0, msg);
212 return FALSE;
213 }
214
215 Thread = CreateThread(NULL,
216 0,
217 StartupWindowThread,
218 (PVOID)msg,
219 0,
220 &ThreadId);
221 if (Thread)
222 {
223 /* 'msg' will be freed by 'StartupWindowThread' */
224
225 CloseHandle(Thread);
226 WaitForSingleObject(msg->StartupEvent, INFINITE);
227 CloseHandle(msg->StartupEvent);
228 return TRUE;
229 }
230 else
231 {
232 /*
233 * The 'StartupWindowThread' thread couldn't be created,
234 * so we need to free the allocated 'msg'.
235 */
236 HeapFree(GetProcessHeap(), 0, msg);
237 }
238
239 return FALSE;
240 }
241
242 if (pTitle)
243 SetWindowTextW(pgContext->hStatusWindow, pTitle);
244
245 SetDlgItemTextW(pgContext->hStatusWindow, IDC_STATUS_MESSAGE, pMessage);
246
247 return TRUE;
248 }
249
250 static BOOL
251 GUIRemoveStatusMessage(
252 IN PGINA_CONTEXT pgContext)
253 {
254 if (pgContext->hStatusWindow)
255 {
256 EndDialog(pgContext->hStatusWindow, 0);
257 pgContext->hStatusWindow = NULL;
258 }
259
260 return TRUE;
261 }
262
263 static INT_PTR CALLBACK
264 WelcomeDialogProc(
265 IN HWND hwndDlg,
266 IN UINT uMsg,
267 IN WPARAM wParam,
268 IN LPARAM lParam)
269 {
270 PDLG_DATA pDlgData;
271
272 pDlgData = (PDLG_DATA)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
273
274 switch (uMsg)
275 {
276 case WM_INITDIALOG:
277 {
278 pDlgData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DLG_DATA));
279 if (pDlgData == NULL)
280 return FALSE;
281
282 SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)pDlgData);
283
284 pDlgData->pgContext = (PGINA_CONTEXT)lParam;
285
286 /* Load the logo bitmap */
287 pDlgData->hBitmap = LoadImageW(pDlgData->pgContext->hDllInstance, MAKEINTRESOURCEW(IDI_ROSLOGO), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
288 return TRUE;
289 }
290
291 case WM_PAINT:
292 {
293 PAINTSTRUCT ps;
294 if (pDlgData->hBitmap)
295 {
296 BeginPaint(hwndDlg, &ps);
297 DrawStateW(ps.hdc, NULL, NULL, (LPARAM)pDlgData->hBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);
298 EndPaint(hwndDlg, &ps);
299 }
300 return TRUE;
301 }
302 case WM_DESTROY:
303 {
304 DeleteObject(pDlgData->hBitmap);
305 HeapFree(GetProcessHeap(), 0, pDlgData);
306 return TRUE;
307 }
308 }
309 return FALSE;
310 }
311
312 static VOID
313 GUIDisplaySASNotice(
314 IN OUT PGINA_CONTEXT pgContext)
315 {
316 TRACE("GUIDisplaySASNotice()\n");
317
318 /* Display the notice window */
319 pgContext->pWlxFuncs->WlxDialogBoxParam(pgContext->hWlx,
320 pgContext->hDllInstance,
321 MAKEINTRESOURCEW(IDD_WELCOME),
322 GetDesktopWindow(),
323 WelcomeDialogProc,
324 (LPARAM)pgContext);
325 }
326
327 /* Get the text contained in a textbox. Allocates memory in pText
328 * to contain the text. Returns TRUE in case of success */
329 static BOOL
330 GetTextboxText(
331 IN HWND hwndDlg,
332 IN INT TextboxId,
333 OUT LPWSTR *pText)
334 {
335 LPWSTR Text;
336 int Count;
337
338 Count = GetWindowTextLength(GetDlgItem(hwndDlg, TextboxId));
339 Text = HeapAlloc(GetProcessHeap(), 0, (Count + 1) * sizeof(WCHAR));
340 if (!Text)
341 return FALSE;
342 if (Count != GetWindowTextW(GetDlgItem(hwndDlg, TextboxId), Text, Count + 1))
343 {
344 HeapFree(GetProcessHeap(), 0, Text);
345 return FALSE;
346 }
347 *pText = Text;
348 return TRUE;
349 }
350
351
352 static
353 INT
354 ResourceMessageBox(
355 IN PGINA_CONTEXT pgContext,
356 IN HWND hwnd,
357 IN UINT uType,
358 IN UINT uCaption,
359 IN UINT uText)
360 {
361 WCHAR szCaption[256];
362 WCHAR szText[256];
363
364 LoadStringW(pgContext->hDllInstance, uCaption, szCaption, _countof(szCaption));
365 LoadStringW(pgContext->hDllInstance, uText, szText, _countof(szText));
366
367 return pgContext->pWlxFuncs->WlxMessageBox(pgContext->hWlx,
368 hwnd,
369 szText,
370 szCaption,
371 uType);
372 }
373
374
375 static
376 BOOL
377 DoChangePassword(
378 IN PGINA_CONTEXT pgContext,
379 IN HWND hwndDlg)
380 {
381 WCHAR UserName[256];
382 WCHAR Domain[256];
383 WCHAR OldPassword[256];
384 WCHAR NewPassword1[256];
385 WCHAR NewPassword2[256];
386 PMSV1_0_CHANGEPASSWORD_REQUEST RequestBuffer = NULL;
387 PMSV1_0_CHANGEPASSWORD_RESPONSE ResponseBuffer = NULL;
388 ULONG RequestBufferSize;
389 ULONG ResponseBufferSize = 0;
390 LPWSTR Ptr;
391 BOOL res = FALSE;
392 NTSTATUS ProtocolStatus;
393 NTSTATUS Status;
394
395 GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_USERNAME, UserName, _countof(UserName));
396 GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_DOMAIN, Domain, _countof(Domain));
397 GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_OLDPWD, OldPassword, _countof(OldPassword));
398 GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_NEWPWD1, NewPassword1, _countof(NewPassword1));
399 GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_NEWPWD2, NewPassword2, _countof(NewPassword2));
400
401 /* Compare the two passwords and fail if they do not match */
402 if (wcscmp(NewPassword1, NewPassword2) != 0)
403 {
404 ResourceMessageBox(pgContext,
405 hwndDlg,
406 MB_OK | MB_ICONEXCLAMATION,
407 IDS_CHANGEPWDTITLE,
408 IDS_NONMATCHINGPASSWORDS);
409 return FALSE;
410 }
411
412 /* Calculate the request buffer size */
413 RequestBufferSize = sizeof(MSV1_0_CHANGEPASSWORD_REQUEST) +
414 ((wcslen(Domain) + 1) * sizeof(WCHAR)) +
415 ((wcslen(UserName) + 1) * sizeof(WCHAR)) +
416 ((wcslen(OldPassword) + 1) * sizeof(WCHAR)) +
417 ((wcslen(NewPassword1) + 1) * sizeof(WCHAR));
418
419 /* Allocate the request buffer */
420 RequestBuffer = HeapAlloc(GetProcessHeap(),
421 HEAP_ZERO_MEMORY,
422 RequestBufferSize);
423 if (RequestBuffer == NULL)
424 {
425 ERR("HeapAlloc failed\n");
426 return FALSE;
427 }
428
429 /* Initialize the request buffer */
430 RequestBuffer->MessageType = MsV1_0ChangePassword;
431 RequestBuffer->Impersonating = TRUE;
432
433 Ptr = (LPWSTR)((ULONG_PTR)RequestBuffer + sizeof(MSV1_0_CHANGEPASSWORD_REQUEST));
434
435 /* Pack the domain name */
436 RequestBuffer->DomainName.Length = wcslen(Domain) * sizeof(WCHAR);
437 RequestBuffer->DomainName.MaximumLength = RequestBuffer->DomainName.Length + sizeof(WCHAR);
438 RequestBuffer->DomainName.Buffer = Ptr;
439
440 RtlCopyMemory(RequestBuffer->DomainName.Buffer,
441 Domain,
442 RequestBuffer->DomainName.MaximumLength);
443
444 Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->DomainName.MaximumLength);
445
446 /* Pack the user name */
447 RequestBuffer->AccountName.Length = wcslen(UserName) * sizeof(WCHAR);
448 RequestBuffer->AccountName.MaximumLength = RequestBuffer->AccountName.Length + sizeof(WCHAR);
449 RequestBuffer->AccountName.Buffer = Ptr;
450
451 RtlCopyMemory(RequestBuffer->AccountName.Buffer,
452 UserName,
453 RequestBuffer->AccountName.MaximumLength);
454
455 Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->AccountName.MaximumLength);
456
457 /* Pack the old password */
458 RequestBuffer->OldPassword.Length = wcslen(OldPassword) * sizeof(WCHAR);
459 RequestBuffer->OldPassword.MaximumLength = RequestBuffer->OldPassword.Length + sizeof(WCHAR);
460 RequestBuffer->OldPassword.Buffer = Ptr;
461
462 RtlCopyMemory(RequestBuffer->OldPassword.Buffer,
463 OldPassword,
464 RequestBuffer->OldPassword.MaximumLength);
465
466 Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->OldPassword.MaximumLength);
467
468 /* Pack the new password */
469 RequestBuffer->NewPassword.Length = wcslen(NewPassword1) * sizeof(WCHAR);
470 RequestBuffer->NewPassword.MaximumLength = RequestBuffer->NewPassword.Length + sizeof(WCHAR);
471 RequestBuffer->NewPassword.Buffer = Ptr;
472
473 RtlCopyMemory(RequestBuffer->NewPassword.Buffer,
474 NewPassword1,
475 RequestBuffer->NewPassword.MaximumLength);
476
477 /* Connect to the LSA server */
478 if (ConnectToLsa(pgContext) != ERROR_SUCCESS)
479 {
480 ERR("ConnectToLsa() failed\n");
481 goto done;
482 }
483
484 /* Call the authentication package */
485 Status = LsaCallAuthenticationPackage(pgContext->LsaHandle,
486 pgContext->AuthenticationPackage,
487 RequestBuffer,
488 RequestBufferSize,
489 (PVOID*)&ResponseBuffer,
490 &ResponseBufferSize,
491 &ProtocolStatus);
492 if (!NT_SUCCESS(Status))
493 {
494 ERR("LsaCallAuthenticationPackage failed (Status 0x%08lx)\n", Status);
495 goto done;
496 }
497
498 if (!NT_SUCCESS(ProtocolStatus))
499 {
500 TRACE("LsaCallAuthenticationPackage failed (ProtocolStatus 0x%08lx)\n", ProtocolStatus);
501 goto done;
502 }
503
504 res = TRUE;
505
506 ResourceMessageBox(pgContext,
507 hwndDlg,
508 MB_OK | MB_ICONINFORMATION,
509 IDS_CHANGEPWDTITLE,
510 IDS_PASSWORDCHANGED);
511
512 if ((wcscmp(UserName, pgContext->UserName) == 0) &&
513 (wcscmp(Domain, pgContext->DomainName) == 0) &&
514 (wcscmp(OldPassword, pgContext->Password) == 0))
515 {
516 ZeroMemory(pgContext->Password, sizeof(pgContext->Password));
517 wcscpy(pgContext->Password, NewPassword1);
518 }
519
520 done:
521 if (RequestBuffer != NULL)
522 HeapFree(GetProcessHeap(), 0, RequestBuffer);
523
524 if (ResponseBuffer != NULL)
525 LsaFreeReturnBuffer(ResponseBuffer);
526
527 return res;
528 }
529
530
531 static INT_PTR CALLBACK
532 ChangePasswordDialogProc(
533 IN HWND hwndDlg,
534 IN UINT uMsg,
535 IN WPARAM wParam,
536 IN LPARAM lParam)
537 {
538 PGINA_CONTEXT pgContext;
539
540 pgContext = (PGINA_CONTEXT)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
541
542 switch (uMsg)
543 {
544 case WM_INITDIALOG:
545 {
546 pgContext = (PGINA_CONTEXT)lParam;
547 SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)pgContext);
548
549 SetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_USERNAME, pgContext->UserName);
550 SendDlgItemMessageW(hwndDlg, IDC_CHANGEPWD_DOMAIN, CB_ADDSTRING, 0, (LPARAM)pgContext->DomainName);
551 SendDlgItemMessageW(hwndDlg, IDC_CHANGEPWD_DOMAIN, CB_SETCURSEL, 0, 0);
552 SetFocus(GetDlgItem(hwndDlg, IDC_CHANGEPWD_OLDPWD));
553 return TRUE;
554 }
555
556 case WM_COMMAND:
557 switch (LOWORD(wParam))
558 {
559 case IDOK:
560 if (DoChangePassword(pgContext, hwndDlg))
561 {
562 EndDialog(hwndDlg, TRUE);
563 }
564 else
565 {
566 SetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_NEWPWD1, NULL);
567 SetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_NEWPWD2, NULL);
568 SetFocus(GetDlgItem(hwndDlg, IDC_CHANGEPWD_OLDPWD));
569 }
570 return TRUE;
571
572 case IDCANCEL:
573 EndDialog(hwndDlg, FALSE);
574 return TRUE;
575 }
576 break;
577
578 case WM_CLOSE:
579 EndDialog(hwndDlg, FALSE);
580 return TRUE;
581 }
582
583 return FALSE;
584 }
585
586
587 static VOID
588 OnInitSecurityDlg(HWND hwnd,
589 PGINA_CONTEXT pgContext)
590 {
591 WCHAR Buffer1[256];
592 WCHAR Buffer2[256];
593 WCHAR Buffer3[256];
594 WCHAR Buffer4[512];
595
596 LoadStringW(pgContext->hDllInstance, IDS_LOGONMSG, Buffer1, _countof(Buffer1));
597
598 wsprintfW(Buffer2, L"%s\\%s", pgContext->DomainName, pgContext->UserName);
599 wsprintfW(Buffer4, Buffer1, Buffer2);
600
601 SetDlgItemTextW(hwnd, IDC_SECURITY_MESSAGE, Buffer4);
602
603 LoadStringW(pgContext->hDllInstance, IDS_LOGONDATE, Buffer1, _countof(Buffer1));
604
605 GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE,
606 (SYSTEMTIME*)&pgContext->LogonTime, NULL, Buffer2, _countof(Buffer2));
607
608 GetTimeFormatW(LOCALE_USER_DEFAULT, 0,
609 (SYSTEMTIME*)&pgContext->LogonTime, NULL, Buffer3, _countof(Buffer3));
610
611 wsprintfW(Buffer4, Buffer1, Buffer2, Buffer3);
612
613 SetDlgItemTextW(hwnd, IDC_SECURITY_LOGONDATE, Buffer4);
614
615 if (pgContext->bAutoAdminLogon)
616 EnableWindow(GetDlgItem(hwnd, IDC_SECURITY_LOGOFF), FALSE);
617 }
618
619
620 static BOOL
621 OnChangePassword(
622 IN HWND hwnd,
623 IN PGINA_CONTEXT pgContext)
624 {
625 INT res;
626
627 TRACE("OnChangePassword()\n");
628
629 res = pgContext->pWlxFuncs->WlxDialogBoxParam(
630 pgContext->hWlx,
631 pgContext->hDllInstance,
632 MAKEINTRESOURCEW(IDD_CHANGEPWD),
633 hwnd,
634 ChangePasswordDialogProc,
635 (LPARAM)pgContext);
636
637 TRACE("Result: %x\n", res);
638
639 return FALSE;
640 }
641
642
643 static INT_PTR CALLBACK
644 LogOffDialogProc(
645 IN HWND hwndDlg,
646 IN UINT uMsg,
647 IN WPARAM wParam,
648 IN LPARAM lParam)
649 {
650 switch (uMsg)
651 {
652 case WM_INITDIALOG:
653 return TRUE;
654
655 case WM_COMMAND:
656 switch (LOWORD(wParam))
657 {
658 case IDYES:
659 EndDialog(hwndDlg, IDYES);
660 return TRUE;
661
662 case IDNO:
663 EndDialog(hwndDlg, IDNO);
664 return TRUE;
665 }
666 break;
667
668 case WM_CLOSE:
669 EndDialog(hwndDlg, IDNO);
670 return TRUE;
671 }
672
673 return FALSE;
674 }
675
676
677 static
678 INT
679 OnLogOff(
680 IN HWND hwndDlg,
681 IN PGINA_CONTEXT pgContext)
682 {
683 return pgContext->pWlxFuncs->WlxDialogBoxParam(
684 pgContext->hWlx,
685 pgContext->hDllInstance,
686 MAKEINTRESOURCEW(IDD_LOGOFF),
687 hwndDlg,
688 LogOffDialogProc,
689 (LPARAM)pgContext);
690 }
691
692
693 static
694 INT
695 OnShutDown(
696 IN HWND hwndDlg,
697 IN PGINA_CONTEXT pgContext)
698 {
699 INT ret;
700 DWORD ShutdownOptions;
701
702 TRACE("OnShutDown(%p %p)\n", hwndDlg, pgContext);
703
704 pgContext->nShutdownAction = GetDefaultShutdownSelState();
705 ShutdownOptions = GetDefaultShutdownOptions();
706
707 if (pgContext->UserToken != NULL)
708 {
709 if (ImpersonateLoggedOnUser(pgContext->UserToken))
710 {
711 pgContext->nShutdownAction = LoadShutdownSelState();
712 ShutdownOptions = GetAllowedShutdownOptions();
713 RevertToSelf();
714 }
715 else
716 {
717 ERR("WL: ImpersonateLoggedOnUser() failed with error %lu\n", GetLastError());
718 }
719 }
720
721 ret = ShutdownDialog(hwndDlg, ShutdownOptions, pgContext);
722
723 if (ret == IDOK)
724 {
725 if (pgContext->UserToken != NULL)
726 {
727 if (ImpersonateLoggedOnUser(pgContext->UserToken))
728 {
729 SaveShutdownSelState(pgContext->nShutdownAction);
730 RevertToSelf();
731 }
732 else
733 {
734 ERR("WL: ImpersonateLoggedOnUser() failed with error %lu\n", GetLastError());
735 }
736 }
737 }
738
739 return ret;
740 }
741
742
743 static INT_PTR CALLBACK
744 SecurityDialogProc(
745 IN HWND hwndDlg,
746 IN UINT uMsg,
747 IN WPARAM wParam,
748 IN LPARAM lParam)
749 {
750 PGINA_CONTEXT pgContext;
751
752 pgContext = (PGINA_CONTEXT)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
753
754 switch (uMsg)
755 {
756 case WM_INITDIALOG:
757 {
758 pgContext = (PGINA_CONTEXT)lParam;
759 SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)pgContext);
760
761 SetWelcomeText(hwndDlg);
762
763 OnInitSecurityDlg(hwndDlg, (PGINA_CONTEXT)lParam);
764 SetFocus(GetDlgItem(hwndDlg, IDNO));
765 return TRUE;
766 }
767
768 case WM_COMMAND:
769 {
770 switch (LOWORD(wParam))
771 {
772 case IDC_SECURITY_LOCK:
773 EndDialog(hwndDlg, WLX_SAS_ACTION_LOCK_WKSTA);
774 return TRUE;
775 case IDC_SECURITY_LOGOFF:
776 if (OnLogOff(hwndDlg, pgContext) == IDYES)
777 EndDialog(hwndDlg, WLX_SAS_ACTION_LOGOFF);
778 return TRUE;
779 case IDC_SECURITY_SHUTDOWN:
780 if (OnShutDown(hwndDlg, pgContext) == IDOK)
781 EndDialog(hwndDlg, pgContext->nShutdownAction);
782 return TRUE;
783 case IDC_SECURITY_CHANGEPWD:
784 if (OnChangePassword(hwndDlg, pgContext))
785 EndDialog(hwndDlg, WLX_SAS_ACTION_PWD_CHANGED);
786 return TRUE;
787 case IDC_SECURITY_TASKMGR:
788 EndDialog(hwndDlg, WLX_SAS_ACTION_TASKLIST);
789 return TRUE;
790 case IDCANCEL:
791 EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
792 return TRUE;
793 }
794 break;
795 }
796 case WM_CLOSE:
797 {
798 EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
799 return TRUE;
800 }
801 }
802
803 return FALSE;
804 }
805
806 static INT
807 GUILoggedOnSAS(
808 IN OUT PGINA_CONTEXT pgContext,
809 IN DWORD dwSasType)
810 {
811 INT result;
812
813 TRACE("GUILoggedOnSAS()\n");
814
815 if (dwSasType != WLX_SAS_TYPE_CTRL_ALT_DEL)
816 {
817 /* Nothing to do for WLX_SAS_TYPE_TIMEOUT ; the dialog will
818 * close itself thanks to the use of WlxDialogBoxParam */
819 return WLX_SAS_ACTION_NONE;
820 }
821
822 pgContext->pWlxFuncs->WlxSwitchDesktopToWinlogon(
823 pgContext->hWlx);
824
825 result = pgContext->pWlxFuncs->WlxDialogBoxParam(
826 pgContext->hWlx,
827 pgContext->hDllInstance,
828 MAKEINTRESOURCEW(IDD_SECURITY),
829 GetDesktopWindow(),
830 SecurityDialogProc,
831 (LPARAM)pgContext);
832
833 if (result < WLX_SAS_ACTION_LOGON ||
834 result > WLX_SAS_ACTION_SWITCH_CONSOLE)
835 {
836 result = WLX_SAS_ACTION_NONE;
837 }
838
839 if (result == WLX_SAS_ACTION_NONE)
840 {
841 pgContext->pWlxFuncs->WlxSwitchDesktopToUser(
842 pgContext->hWlx);
843 }
844
845 return result;
846 }
847
848
849 static
850 BOOL
851 DoLogon(
852 IN HWND hwndDlg,
853 IN OUT PGINA_CONTEXT pgContext)
854 {
855 LPWSTR UserName = NULL;
856 LPWSTR Password = NULL;
857 LPWSTR Domain = NULL;
858 BOOL result = FALSE;
859 NTSTATUS Status, SubStatus = STATUS_SUCCESS;
860
861 if (GetTextboxText(hwndDlg, IDC_LOGON_USERNAME, &UserName) && *UserName == '\0')
862 goto done;
863
864 if (GetTextboxText(hwndDlg, IDC_LOGON_DOMAIN, &Domain) && *Domain == '\0')
865 goto done;
866
867 if (!GetTextboxText(hwndDlg, IDC_LOGON_PASSWORD, &Password))
868 goto done;
869
870 Status = DoLoginTasks(pgContext, UserName, Domain, Password, &SubStatus);
871 if (Status == STATUS_LOGON_FAILURE)
872 {
873 ResourceMessageBox(pgContext,
874 hwndDlg,
875 MB_OK | MB_ICONEXCLAMATION,
876 IDS_LOGONTITLE,
877 IDS_LOGONWRONGUSERORPWD);
878 goto done;
879 }
880 else if (Status == STATUS_ACCOUNT_RESTRICTION)
881 {
882 TRACE("DoLoginTasks failed! Status 0x%08lx SubStatus 0x%08lx\n", Status, SubStatus);
883
884 if (SubStatus == STATUS_ACCOUNT_DISABLED)
885 {
886 ResourceMessageBox(pgContext,
887 hwndDlg,
888 MB_OK | MB_ICONEXCLAMATION,
889 IDS_LOGONTITLE,
890 IDS_LOGONUSERDISABLED);
891 goto done;
892 }
893 else if (SubStatus == STATUS_ACCOUNT_LOCKED_OUT)
894 {
895 TRACE("Account locked!\n");
896 pgContext->pWlxFuncs->WlxMessageBox(pgContext->hWlx,
897 hwndDlg,
898 L"Account locked!",
899 L"Logon error",
900 MB_OK | MB_ICONERROR);
901 goto done;
902 }
903 else if ((SubStatus == STATUS_PASSWORD_MUST_CHANGE) ||
904 (SubStatus == STATUS_PASSWORD_EXPIRED))
905 {
906 if (SubStatus == STATUS_PASSWORD_MUST_CHANGE)
907 ResourceMessageBox(pgContext,
908 hwndDlg,
909 MB_OK | MB_ICONSTOP,
910 IDS_LOGONTITLE,
911 IDS_PASSWORDMUSTCHANGE);
912 else
913 ResourceMessageBox(pgContext,
914 hwndDlg,
915 MB_OK | MB_ICONSTOP,
916 IDS_LOGONTITLE,
917 IDS_PASSWORDEXPIRED);
918
919 if (!OnChangePassword(hwndDlg,
920 pgContext))
921 goto done;
922
923 Status = DoLoginTasks(pgContext,
924 pgContext->UserName,
925 pgContext->DomainName,
926 pgContext->Password,
927 &SubStatus);
928 if (!NT_SUCCESS(Status))
929 {
930 TRACE("Login after password change failed! (Status 0x%08lx)\n", Status);
931
932 goto done;
933 }
934 }
935 else
936 {
937 TRACE("Other error!\n");
938 pgContext->pWlxFuncs->WlxMessageBox(pgContext->hWlx,
939 hwndDlg,
940 L"Other error!",
941 L"Logon error",
942 MB_OK | MB_ICONERROR);
943 goto done;
944 }
945 }
946 else if (!NT_SUCCESS(Status))
947 {
948 TRACE("DoLoginTasks failed! Status 0x%08lx\n", Status);
949 goto done;
950 }
951
952
953 if (!CreateProfile(pgContext, UserName, Domain, Password))
954 {
955 ERR("Failed to create the profile!\n");
956 goto done;
957 }
958
959 ZeroMemory(pgContext->Password, sizeof(pgContext->Password));
960 wcscpy(pgContext->Password, Password);
961
962 result = TRUE;
963
964 done:
965 pgContext->bAutoAdminLogon = FALSE;
966
967 if (UserName != NULL)
968 HeapFree(GetProcessHeap(), 0, UserName);
969
970 if (Password != NULL)
971 HeapFree(GetProcessHeap(), 0, Password);
972
973 if (Domain != NULL)
974 HeapFree(GetProcessHeap(), 0, Domain);
975
976 return result;
977 }
978
979
980 static
981 VOID
982 SetDomainComboBox(
983 HWND hwndDomainComboBox,
984 PGINA_CONTEXT pgContext)
985 {
986 WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
987 DWORD dwComputerNameLength;
988 LONG lIndex = 0;
989 LONG lFindIndex;
990
991 SendMessageW(hwndDomainComboBox, CB_RESETCONTENT, 0, 0);
992
993 dwComputerNameLength = _countof(szComputerName);
994 if (GetComputerNameW(szComputerName, &dwComputerNameLength))
995 {
996 lIndex = SendMessageW(hwndDomainComboBox, CB_ADDSTRING, 0, (LPARAM)szComputerName);
997 }
998
999 if (wcslen(pgContext->DomainName) != 0)
1000 {
1001 lFindIndex = SendMessageW(hwndDomainComboBox, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)pgContext->DomainName);
1002 if (lFindIndex == CB_ERR)
1003 {
1004 lIndex = SendMessageW(hwndDomainComboBox, CB_ADDSTRING, 0, (LPARAM)pgContext->DomainName);
1005 }
1006 else
1007 {
1008 lIndex = lFindIndex;
1009 }
1010 }
1011
1012 SendMessageW(hwndDomainComboBox, CB_SETCURSEL, lIndex, 0);
1013 }
1014
1015
1016 static INT_PTR CALLBACK
1017 LogonDialogProc(
1018 IN HWND hwndDlg,
1019 IN UINT uMsg,
1020 IN WPARAM wParam,
1021 IN LPARAM lParam)
1022 {
1023 PDLG_DATA pDlgData;
1024
1025 pDlgData = (PDLG_DATA)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
1026
1027 switch (uMsg)
1028 {
1029 case WM_INITDIALOG:
1030 {
1031 pDlgData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DLG_DATA));
1032 if (pDlgData == NULL)
1033 return FALSE;
1034
1035 SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)pDlgData);
1036
1037 /* FIXME: take care of NoDomainUI */
1038 pDlgData->pgContext = (PGINA_CONTEXT)lParam;
1039
1040 /* Draw the logo bitmap */
1041 pDlgData->hBitmap = LoadImageW(pDlgData->pgContext->hDllInstance, MAKEINTRESOURCEW(IDI_ROSLOGO), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
1042
1043 SetWelcomeText(hwndDlg);
1044
1045 if (pDlgData->pgContext->bAutoAdminLogon ||
1046 !pDlgData->pgContext->bDontDisplayLastUserName)
1047 SetDlgItemTextW(hwndDlg, IDC_LOGON_USERNAME, pDlgData->pgContext->UserName);
1048
1049 if (pDlgData->pgContext->bAutoAdminLogon)
1050 SetDlgItemTextW(hwndDlg, IDC_LOGON_PASSWORD, pDlgData->pgContext->Password);
1051
1052 SetDomainComboBox(GetDlgItem(hwndDlg, IDC_LOGON_DOMAIN), pDlgData->pgContext);
1053
1054 if (pDlgData->pgContext->bDisableCAD)
1055 EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), FALSE);
1056
1057 if (!pDlgData->pgContext->bShutdownWithoutLogon)
1058 EnableWindow(GetDlgItem(hwndDlg, IDC_LOGON_SHUTDOWN), FALSE);
1059
1060 SetFocus(GetDlgItem(hwndDlg, pDlgData->pgContext->bDontDisplayLastUserName ? IDC_LOGON_USERNAME : IDC_LOGON_PASSWORD));
1061
1062 if (pDlgData->pgContext->bAutoAdminLogon)
1063 PostMessage(GetDlgItem(hwndDlg, IDOK), BM_CLICK, 0, 0);
1064
1065 return TRUE;
1066 }
1067
1068 case WM_PAINT:
1069 {
1070 PAINTSTRUCT ps;
1071 if (pDlgData->hBitmap)
1072 {
1073 BeginPaint(hwndDlg, &ps);
1074 DrawStateW(ps.hdc, NULL, NULL, (LPARAM)pDlgData->hBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);
1075 EndPaint(hwndDlg, &ps);
1076 }
1077 return TRUE;
1078 }
1079
1080 case WM_DESTROY:
1081 DeleteObject(pDlgData->hBitmap);
1082 HeapFree(GetProcessHeap(), 0, pDlgData);
1083 return TRUE;
1084
1085 case WM_COMMAND:
1086 switch (LOWORD(wParam))
1087 {
1088 case IDOK:
1089 if (DoLogon(hwndDlg, pDlgData->pgContext))
1090 EndDialog(hwndDlg, WLX_SAS_ACTION_LOGON);
1091 return TRUE;
1092
1093 case IDCANCEL:
1094 EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
1095 return TRUE;
1096
1097 case IDC_LOGON_SHUTDOWN:
1098 if (OnShutDown(hwndDlg, pDlgData->pgContext) == IDOK)
1099 EndDialog(hwndDlg, pDlgData->pgContext->nShutdownAction);
1100 return TRUE;
1101 }
1102 break;
1103 }
1104
1105 return FALSE;
1106 }
1107
1108
1109 static
1110 INT_PTR
1111 CALLBACK
1112 LegalNoticeDialogProc(
1113 IN HWND hwndDlg,
1114 IN UINT uMsg,
1115 IN WPARAM wParam,
1116 IN LPARAM lParam)
1117 {
1118 PLEGALNOTICEDATA pLegalNotice;
1119
1120 switch (uMsg)
1121 {
1122 case WM_INITDIALOG:
1123 pLegalNotice = (PLEGALNOTICEDATA)lParam;
1124 SetWindowTextW(hwndDlg, pLegalNotice->pszCaption);
1125 SetDlgItemTextW(hwndDlg, IDC_LEGALNOTICE_TEXT, pLegalNotice->pszText);
1126 return TRUE;
1127
1128 case WM_COMMAND:
1129 switch (LOWORD(wParam))
1130 {
1131 case IDOK:
1132 EndDialog(hwndDlg, 0);
1133 return TRUE;
1134
1135 case IDCANCEL:
1136 EndDialog(hwndDlg, 0);
1137 return TRUE;
1138 }
1139 break;
1140 }
1141
1142 return FALSE;
1143 }
1144
1145
1146 static INT
1147 GUILoggedOutSAS(
1148 IN OUT PGINA_CONTEXT pgContext)
1149 {
1150 LEGALNOTICEDATA LegalNotice = {NULL, NULL};
1151 HKEY hKey = NULL;
1152 LONG rc;
1153 int result;
1154
1155 TRACE("GUILoggedOutSAS()\n");
1156
1157 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1158 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
1159 0,
1160 KEY_QUERY_VALUE,
1161 &hKey);
1162 if (rc == ERROR_SUCCESS)
1163 {
1164 ReadRegSzValue(hKey,
1165 L"LegalNoticeCaption",
1166 &LegalNotice.pszCaption);
1167
1168 ReadRegSzValue(hKey,
1169 L"LegalNoticeText",
1170 &LegalNotice.pszText);
1171
1172 RegCloseKey(hKey);
1173 }
1174
1175 if (LegalNotice.pszCaption != NULL && wcslen(LegalNotice.pszCaption) != 0 &&
1176 LegalNotice.pszText != NULL && wcslen(LegalNotice.pszText) != 0)
1177 {
1178 pgContext->pWlxFuncs->WlxDialogBoxParam(pgContext->hWlx,
1179 pgContext->hDllInstance,
1180 MAKEINTRESOURCEW(IDD_LEGALNOTICE),
1181 GetDesktopWindow(),
1182 LegalNoticeDialogProc,
1183 (LPARAM)&LegalNotice);
1184 }
1185
1186 if (LegalNotice.pszCaption != NULL)
1187 HeapFree(GetProcessHeap(), 0, LegalNotice.pszCaption);
1188
1189 if (LegalNotice.pszText != NULL)
1190 HeapFree(GetProcessHeap(), 0, LegalNotice.pszText);
1191
1192 result = pgContext->pWlxFuncs->WlxDialogBoxParam(
1193 pgContext->hWlx,
1194 pgContext->hDllInstance,
1195 MAKEINTRESOURCEW(IDD_LOGON),
1196 GetDesktopWindow(),
1197 LogonDialogProc,
1198 (LPARAM)pgContext);
1199 if (result >= WLX_SAS_ACTION_LOGON &&
1200 result <= WLX_SAS_ACTION_SWITCH_CONSOLE)
1201 {
1202 WARN("WlxLoggedOutSAS() returns 0x%x\n", result);
1203 return result;
1204 }
1205
1206 WARN("WlxDialogBoxParam() failed (0x%x)\n", result);
1207 return WLX_SAS_ACTION_NONE;
1208 }
1209
1210
1211 static VOID
1212 SetLockMessage(HWND hwnd,
1213 INT nDlgItem,
1214 PGINA_CONTEXT pgContext)
1215 {
1216 WCHAR Buffer1[256];
1217 WCHAR Buffer2[256];
1218 WCHAR Buffer3[512];
1219
1220 LoadStringW(pgContext->hDllInstance, IDS_LOCKMSG, Buffer1, _countof(Buffer1));
1221
1222 wsprintfW(Buffer2, L"%s\\%s", pgContext->DomainName, pgContext->UserName);
1223 wsprintfW(Buffer3, Buffer1, Buffer2);
1224
1225 SetDlgItemTextW(hwnd, nDlgItem, Buffer3);
1226 }
1227
1228
1229 static
1230 BOOL
1231 DoUnlock(
1232 IN HWND hwndDlg,
1233 IN PGINA_CONTEXT pgContext,
1234 OUT LPINT Action)
1235 {
1236 WCHAR Buffer1[256];
1237 WCHAR Buffer2[256];
1238 LPWSTR UserName = NULL;
1239 LPWSTR Password = NULL;
1240 BOOL res = FALSE;
1241
1242 if (GetTextboxText(hwndDlg, IDC_UNLOCK_USERNAME, &UserName) && *UserName == '\0')
1243 {
1244 HeapFree(GetProcessHeap(), 0, UserName);
1245 return FALSE;
1246 }
1247
1248 if (GetTextboxText(hwndDlg, IDC_UNLOCK_PASSWORD, &Password))
1249 {
1250 if (UserName != NULL && Password != NULL &&
1251 wcscmp(UserName, pgContext->UserName) == 0 &&
1252 wcscmp(Password, pgContext->Password) == 0)
1253 {
1254 *Action = WLX_SAS_ACTION_UNLOCK_WKSTA;
1255 res = TRUE;
1256 }
1257 else if (wcscmp(UserName, pgContext->UserName) == 0 &&
1258 wcscmp(Password, pgContext->Password) != 0)
1259 {
1260 /* Wrong Password */
1261 LoadStringW(pgContext->hDllInstance, IDS_LOCKEDWRONGPASSWORD, Buffer2, _countof(Buffer2));
1262 LoadStringW(pgContext->hDllInstance, IDS_COMPUTERLOCKED, Buffer1, _countof(Buffer1));
1263 MessageBoxW(hwndDlg, Buffer2, Buffer1, MB_OK | MB_ICONERROR);
1264 }
1265 else
1266 {
1267 /* Wrong user name */
1268 if (DoAdminUnlock(pgContext, UserName, NULL, Password))
1269 {
1270 *Action = WLX_SAS_ACTION_UNLOCK_WKSTA;
1271 res = TRUE;
1272 }
1273 else
1274 {
1275 LoadStringW(pgContext->hDllInstance, IDS_LOCKEDWRONGUSER, Buffer1, _countof(Buffer1));
1276 wsprintfW(Buffer2, Buffer1, pgContext->DomainName, pgContext->UserName);
1277 LoadStringW(pgContext->hDllInstance, IDS_COMPUTERLOCKED, Buffer1, _countof(Buffer1));
1278 MessageBoxW(hwndDlg, Buffer2, Buffer1, MB_OK | MB_ICONERROR);
1279 }
1280 }
1281 }
1282
1283 if (UserName != NULL)
1284 HeapFree(GetProcessHeap(), 0, UserName);
1285
1286 if (Password != NULL)
1287 HeapFree(GetProcessHeap(), 0, Password);
1288
1289 return res;
1290 }
1291
1292
1293 static
1294 INT_PTR
1295 CALLBACK
1296 UnlockDialogProc(
1297 IN HWND hwndDlg,
1298 IN UINT uMsg,
1299 IN WPARAM wParam,
1300 IN LPARAM lParam)
1301 {
1302 PDLG_DATA pDlgData;
1303 INT result = WLX_SAS_ACTION_NONE;
1304
1305 pDlgData = (PDLG_DATA)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
1306
1307 switch (uMsg)
1308 {
1309 case WM_INITDIALOG:
1310 {
1311 pDlgData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DLG_DATA));
1312 if (pDlgData == NULL)
1313 return FALSE;
1314
1315 SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)pDlgData);
1316
1317 pDlgData->pgContext = (PGINA_CONTEXT)lParam;
1318
1319 SetWelcomeText(hwndDlg);
1320
1321 SetLockMessage(hwndDlg, IDC_UNLOCK_MESSAGE, pDlgData->pgContext);
1322
1323 SetDlgItemTextW(hwndDlg, IDC_UNLOCK_USERNAME, pDlgData->pgContext->UserName);
1324 SetFocus(GetDlgItem(hwndDlg, IDC_UNLOCK_PASSWORD));
1325
1326 if (pDlgData->pgContext->bDisableCAD)
1327 EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), FALSE);
1328
1329 /* Load the logo bitmap */
1330 pDlgData->hBitmap = LoadImageW(pDlgData->pgContext->hDllInstance, MAKEINTRESOURCEW(IDI_ROSLOGO), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
1331 return TRUE;
1332 }
1333
1334 case WM_PAINT:
1335 {
1336 PAINTSTRUCT ps;
1337 if (pDlgData->hBitmap)
1338 {
1339 BeginPaint(hwndDlg, &ps);
1340 DrawStateW(ps.hdc, NULL, NULL, (LPARAM)pDlgData->hBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);
1341 EndPaint(hwndDlg, &ps);
1342 }
1343 return TRUE;
1344 }
1345 case WM_DESTROY:
1346 DeleteObject(pDlgData->hBitmap);
1347 HeapFree(GetProcessHeap(), 0, pDlgData);
1348 return TRUE;
1349
1350 case WM_COMMAND:
1351 switch (LOWORD(wParam))
1352 {
1353 case IDOK:
1354 if (DoUnlock(hwndDlg, pDlgData->pgContext, &result))
1355 EndDialog(hwndDlg, result);
1356 return TRUE;
1357
1358 case IDCANCEL:
1359 EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
1360 return TRUE;
1361 }
1362 break;
1363 }
1364
1365 return FALSE;
1366 }
1367
1368
1369 static INT
1370 GUILockedSAS(
1371 IN OUT PGINA_CONTEXT pgContext)
1372 {
1373 int result;
1374
1375 TRACE("GUILockedSAS()\n");
1376
1377 result = pgContext->pWlxFuncs->WlxDialogBoxParam(
1378 pgContext->hWlx,
1379 pgContext->hDllInstance,
1380 MAKEINTRESOURCEW(IDD_UNLOCK),
1381 GetDesktopWindow(),
1382 UnlockDialogProc,
1383 (LPARAM)pgContext);
1384 if (result >= WLX_SAS_ACTION_LOGON &&
1385 result <= WLX_SAS_ACTION_SWITCH_CONSOLE)
1386 {
1387 WARN("GUILockedSAS() returns 0x%x\n", result);
1388 return result;
1389 }
1390
1391 WARN("GUILockedSAS() failed (0x%x)\n", result);
1392 return WLX_SAS_ACTION_NONE;
1393 }
1394
1395
1396 static INT_PTR CALLBACK
1397 LockedDialogProc(
1398 IN HWND hwndDlg,
1399 IN UINT uMsg,
1400 IN WPARAM wParam,
1401 IN LPARAM lParam)
1402 {
1403 PDLG_DATA pDlgData;
1404
1405 pDlgData = (PDLG_DATA)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
1406
1407 switch (uMsg)
1408 {
1409 case WM_INITDIALOG:
1410 {
1411 pDlgData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DLG_DATA));
1412 if (pDlgData == NULL)
1413 return FALSE;
1414
1415 SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)pDlgData);
1416
1417 pDlgData->pgContext = (PGINA_CONTEXT)lParam;
1418
1419 /* Load the logo bitmap */
1420 pDlgData->hBitmap = LoadImageW(pDlgData->pgContext->hDllInstance, MAKEINTRESOURCEW(IDI_ROSLOGO), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
1421
1422 SetWelcomeText(hwndDlg);
1423
1424 SetLockMessage(hwndDlg, IDC_LOCKED_MESSAGE, pDlgData->pgContext);
1425 return TRUE;
1426 }
1427 case WM_PAINT:
1428 {
1429 PAINTSTRUCT ps;
1430 if (pDlgData->hBitmap)
1431 {
1432 BeginPaint(hwndDlg, &ps);
1433 DrawStateW(ps.hdc, NULL, NULL, (LPARAM)pDlgData->hBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);
1434 EndPaint(hwndDlg, &ps);
1435 }
1436 return TRUE;
1437 }
1438 case WM_DESTROY:
1439 {
1440 DeleteObject(pDlgData->hBitmap);
1441 HeapFree(GetProcessHeap(), 0, pDlgData);
1442 return TRUE;
1443 }
1444 }
1445
1446 return FALSE;
1447 }
1448
1449
1450 static VOID
1451 GUIDisplayLockedNotice(
1452 IN OUT PGINA_CONTEXT pgContext)
1453 {
1454 TRACE("GUIdisplayLockedNotice()\n");
1455
1456 pgContext->pWlxFuncs->WlxDialogBoxParam(
1457 pgContext->hWlx,
1458 pgContext->hDllInstance,
1459 MAKEINTRESOURCEW(IDD_LOCKED),
1460 GetDesktopWindow(),
1461 LockedDialogProc,
1462 (LPARAM)pgContext);
1463 }
1464
1465 GINA_UI GinaGraphicalUI = {
1466 GUIInitialize,
1467 GUIDisplayStatusMessage,
1468 GUIRemoveStatusMessage,
1469 GUIDisplaySASNotice,
1470 GUILoggedOnSAS,
1471 GUILoggedOutSAS,
1472 GUILockedSAS,
1473 GUIDisplayLockedNotice,
1474 };