cafced9aa22f7f1e1f3e943f2f6715e2697e254b
[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 if (SubStatus == STATUS_ACCOUNT_EXPIRED)
936 {
937 ResourceMessageBox(pgContext,
938 hwndDlg,
939 MB_OK | MB_ICONEXCLAMATION,
940 IDS_LOGONTITLE,
941 IDS_ACCOUNTEXPIRED);
942 }
943 else
944 {
945 TRACE("Other error!\n");
946 pgContext->pWlxFuncs->WlxMessageBox(pgContext->hWlx,
947 hwndDlg,
948 L"Other error!",
949 L"Logon error",
950 MB_OK | MB_ICONERROR);
951 goto done;
952 }
953 }
954 else if (!NT_SUCCESS(Status))
955 {
956 TRACE("DoLoginTasks failed! Status 0x%08lx\n", Status);
957 goto done;
958 }
959
960
961 if (!CreateProfile(pgContext, UserName, Domain, Password))
962 {
963 ERR("Failed to create the profile!\n");
964 goto done;
965 }
966
967 ZeroMemory(pgContext->Password, sizeof(pgContext->Password));
968 wcscpy(pgContext->Password, Password);
969
970 result = TRUE;
971
972 done:
973 pgContext->bAutoAdminLogon = FALSE;
974
975 if (UserName != NULL)
976 HeapFree(GetProcessHeap(), 0, UserName);
977
978 if (Password != NULL)
979 HeapFree(GetProcessHeap(), 0, Password);
980
981 if (Domain != NULL)
982 HeapFree(GetProcessHeap(), 0, Domain);
983
984 return result;
985 }
986
987
988 static
989 VOID
990 SetDomainComboBox(
991 HWND hwndDomainComboBox,
992 PGINA_CONTEXT pgContext)
993 {
994 WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
995 DWORD dwComputerNameLength;
996 LONG lIndex = 0;
997 LONG lFindIndex;
998
999 SendMessageW(hwndDomainComboBox, CB_RESETCONTENT, 0, 0);
1000
1001 dwComputerNameLength = _countof(szComputerName);
1002 if (GetComputerNameW(szComputerName, &dwComputerNameLength))
1003 {
1004 lIndex = SendMessageW(hwndDomainComboBox, CB_ADDSTRING, 0, (LPARAM)szComputerName);
1005 }
1006
1007 if (wcslen(pgContext->DomainName) != 0)
1008 {
1009 lFindIndex = SendMessageW(hwndDomainComboBox, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)pgContext->DomainName);
1010 if (lFindIndex == CB_ERR)
1011 {
1012 lIndex = SendMessageW(hwndDomainComboBox, CB_ADDSTRING, 0, (LPARAM)pgContext->DomainName);
1013 }
1014 else
1015 {
1016 lIndex = lFindIndex;
1017 }
1018 }
1019
1020 SendMessageW(hwndDomainComboBox, CB_SETCURSEL, lIndex, 0);
1021 }
1022
1023
1024 static INT_PTR CALLBACK
1025 LogonDialogProc(
1026 IN HWND hwndDlg,
1027 IN UINT uMsg,
1028 IN WPARAM wParam,
1029 IN LPARAM lParam)
1030 {
1031 PDLG_DATA pDlgData;
1032
1033 pDlgData = (PDLG_DATA)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
1034
1035 switch (uMsg)
1036 {
1037 case WM_INITDIALOG:
1038 {
1039 pDlgData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DLG_DATA));
1040 if (pDlgData == NULL)
1041 return FALSE;
1042
1043 SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)pDlgData);
1044
1045 /* FIXME: take care of NoDomainUI */
1046 pDlgData->pgContext = (PGINA_CONTEXT)lParam;
1047
1048 /* Draw the logo bitmap */
1049 pDlgData->hBitmap = LoadImageW(pDlgData->pgContext->hDllInstance, MAKEINTRESOURCEW(IDI_ROSLOGO), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
1050
1051 SetWelcomeText(hwndDlg);
1052
1053 if (pDlgData->pgContext->bAutoAdminLogon ||
1054 !pDlgData->pgContext->bDontDisplayLastUserName)
1055 SetDlgItemTextW(hwndDlg, IDC_LOGON_USERNAME, pDlgData->pgContext->UserName);
1056
1057 if (pDlgData->pgContext->bAutoAdminLogon)
1058 SetDlgItemTextW(hwndDlg, IDC_LOGON_PASSWORD, pDlgData->pgContext->Password);
1059
1060 SetDomainComboBox(GetDlgItem(hwndDlg, IDC_LOGON_DOMAIN), pDlgData->pgContext);
1061
1062 if (pDlgData->pgContext->bDisableCAD)
1063 EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), FALSE);
1064
1065 if (!pDlgData->pgContext->bShutdownWithoutLogon)
1066 EnableWindow(GetDlgItem(hwndDlg, IDC_LOGON_SHUTDOWN), FALSE);
1067
1068 SetFocus(GetDlgItem(hwndDlg, pDlgData->pgContext->bDontDisplayLastUserName ? IDC_LOGON_USERNAME : IDC_LOGON_PASSWORD));
1069
1070 if (pDlgData->pgContext->bAutoAdminLogon)
1071 PostMessage(GetDlgItem(hwndDlg, IDOK), BM_CLICK, 0, 0);
1072
1073 return TRUE;
1074 }
1075
1076 case WM_PAINT:
1077 {
1078 PAINTSTRUCT ps;
1079 if (pDlgData->hBitmap)
1080 {
1081 BeginPaint(hwndDlg, &ps);
1082 DrawStateW(ps.hdc, NULL, NULL, (LPARAM)pDlgData->hBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);
1083 EndPaint(hwndDlg, &ps);
1084 }
1085 return TRUE;
1086 }
1087
1088 case WM_DESTROY:
1089 DeleteObject(pDlgData->hBitmap);
1090 HeapFree(GetProcessHeap(), 0, pDlgData);
1091 return TRUE;
1092
1093 case WM_COMMAND:
1094 switch (LOWORD(wParam))
1095 {
1096 case IDOK:
1097 if (DoLogon(hwndDlg, pDlgData->pgContext))
1098 EndDialog(hwndDlg, WLX_SAS_ACTION_LOGON);
1099 return TRUE;
1100
1101 case IDCANCEL:
1102 EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
1103 return TRUE;
1104
1105 case IDC_LOGON_SHUTDOWN:
1106 if (OnShutDown(hwndDlg, pDlgData->pgContext) == IDOK)
1107 EndDialog(hwndDlg, pDlgData->pgContext->nShutdownAction);
1108 return TRUE;
1109 }
1110 break;
1111 }
1112
1113 return FALSE;
1114 }
1115
1116
1117 static
1118 INT_PTR
1119 CALLBACK
1120 LegalNoticeDialogProc(
1121 IN HWND hwndDlg,
1122 IN UINT uMsg,
1123 IN WPARAM wParam,
1124 IN LPARAM lParam)
1125 {
1126 PLEGALNOTICEDATA pLegalNotice;
1127
1128 switch (uMsg)
1129 {
1130 case WM_INITDIALOG:
1131 pLegalNotice = (PLEGALNOTICEDATA)lParam;
1132 SetWindowTextW(hwndDlg, pLegalNotice->pszCaption);
1133 SetDlgItemTextW(hwndDlg, IDC_LEGALNOTICE_TEXT, pLegalNotice->pszText);
1134 return TRUE;
1135
1136 case WM_COMMAND:
1137 switch (LOWORD(wParam))
1138 {
1139 case IDOK:
1140 EndDialog(hwndDlg, 0);
1141 return TRUE;
1142
1143 case IDCANCEL:
1144 EndDialog(hwndDlg, 0);
1145 return TRUE;
1146 }
1147 break;
1148 }
1149
1150 return FALSE;
1151 }
1152
1153
1154 static INT
1155 GUILoggedOutSAS(
1156 IN OUT PGINA_CONTEXT pgContext)
1157 {
1158 LEGALNOTICEDATA LegalNotice = {NULL, NULL};
1159 HKEY hKey = NULL;
1160 LONG rc;
1161 int result;
1162
1163 TRACE("GUILoggedOutSAS()\n");
1164
1165 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1166 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
1167 0,
1168 KEY_QUERY_VALUE,
1169 &hKey);
1170 if (rc == ERROR_SUCCESS)
1171 {
1172 ReadRegSzValue(hKey,
1173 L"LegalNoticeCaption",
1174 &LegalNotice.pszCaption);
1175
1176 ReadRegSzValue(hKey,
1177 L"LegalNoticeText",
1178 &LegalNotice.pszText);
1179
1180 RegCloseKey(hKey);
1181 }
1182
1183 if (LegalNotice.pszCaption != NULL && wcslen(LegalNotice.pszCaption) != 0 &&
1184 LegalNotice.pszText != NULL && wcslen(LegalNotice.pszText) != 0)
1185 {
1186 pgContext->pWlxFuncs->WlxDialogBoxParam(pgContext->hWlx,
1187 pgContext->hDllInstance,
1188 MAKEINTRESOURCEW(IDD_LEGALNOTICE),
1189 GetDesktopWindow(),
1190 LegalNoticeDialogProc,
1191 (LPARAM)&LegalNotice);
1192 }
1193
1194 if (LegalNotice.pszCaption != NULL)
1195 HeapFree(GetProcessHeap(), 0, LegalNotice.pszCaption);
1196
1197 if (LegalNotice.pszText != NULL)
1198 HeapFree(GetProcessHeap(), 0, LegalNotice.pszText);
1199
1200 result = pgContext->pWlxFuncs->WlxDialogBoxParam(
1201 pgContext->hWlx,
1202 pgContext->hDllInstance,
1203 MAKEINTRESOURCEW(IDD_LOGON),
1204 GetDesktopWindow(),
1205 LogonDialogProc,
1206 (LPARAM)pgContext);
1207 if (result >= WLX_SAS_ACTION_LOGON &&
1208 result <= WLX_SAS_ACTION_SWITCH_CONSOLE)
1209 {
1210 WARN("WlxLoggedOutSAS() returns 0x%x\n", result);
1211 return result;
1212 }
1213
1214 WARN("WlxDialogBoxParam() failed (0x%x)\n", result);
1215 return WLX_SAS_ACTION_NONE;
1216 }
1217
1218
1219 static VOID
1220 SetLockMessage(HWND hwnd,
1221 INT nDlgItem,
1222 PGINA_CONTEXT pgContext)
1223 {
1224 WCHAR Buffer1[256];
1225 WCHAR Buffer2[256];
1226 WCHAR Buffer3[512];
1227
1228 LoadStringW(pgContext->hDllInstance, IDS_LOCKMSG, Buffer1, _countof(Buffer1));
1229
1230 wsprintfW(Buffer2, L"%s\\%s", pgContext->DomainName, pgContext->UserName);
1231 wsprintfW(Buffer3, Buffer1, Buffer2);
1232
1233 SetDlgItemTextW(hwnd, nDlgItem, Buffer3);
1234 }
1235
1236
1237 static
1238 BOOL
1239 DoUnlock(
1240 IN HWND hwndDlg,
1241 IN PGINA_CONTEXT pgContext,
1242 OUT LPINT Action)
1243 {
1244 WCHAR Buffer1[256];
1245 WCHAR Buffer2[256];
1246 LPWSTR UserName = NULL;
1247 LPWSTR Password = NULL;
1248 BOOL res = FALSE;
1249
1250 if (GetTextboxText(hwndDlg, IDC_UNLOCK_USERNAME, &UserName) && *UserName == '\0')
1251 {
1252 HeapFree(GetProcessHeap(), 0, UserName);
1253 return FALSE;
1254 }
1255
1256 if (GetTextboxText(hwndDlg, IDC_UNLOCK_PASSWORD, &Password))
1257 {
1258 if (UserName != NULL && Password != NULL &&
1259 wcscmp(UserName, pgContext->UserName) == 0 &&
1260 wcscmp(Password, pgContext->Password) == 0)
1261 {
1262 *Action = WLX_SAS_ACTION_UNLOCK_WKSTA;
1263 res = TRUE;
1264 }
1265 else if (wcscmp(UserName, pgContext->UserName) == 0 &&
1266 wcscmp(Password, pgContext->Password) != 0)
1267 {
1268 /* Wrong Password */
1269 LoadStringW(pgContext->hDllInstance, IDS_LOCKEDWRONGPASSWORD, Buffer2, _countof(Buffer2));
1270 LoadStringW(pgContext->hDllInstance, IDS_COMPUTERLOCKED, Buffer1, _countof(Buffer1));
1271 MessageBoxW(hwndDlg, Buffer2, Buffer1, MB_OK | MB_ICONERROR);
1272 }
1273 else
1274 {
1275 /* Wrong user name */
1276 if (DoAdminUnlock(pgContext, UserName, NULL, Password))
1277 {
1278 *Action = WLX_SAS_ACTION_UNLOCK_WKSTA;
1279 res = TRUE;
1280 }
1281 else
1282 {
1283 LoadStringW(pgContext->hDllInstance, IDS_LOCKEDWRONGUSER, Buffer1, _countof(Buffer1));
1284 wsprintfW(Buffer2, Buffer1, pgContext->DomainName, pgContext->UserName);
1285 LoadStringW(pgContext->hDllInstance, IDS_COMPUTERLOCKED, Buffer1, _countof(Buffer1));
1286 MessageBoxW(hwndDlg, Buffer2, Buffer1, MB_OK | MB_ICONERROR);
1287 }
1288 }
1289 }
1290
1291 if (UserName != NULL)
1292 HeapFree(GetProcessHeap(), 0, UserName);
1293
1294 if (Password != NULL)
1295 HeapFree(GetProcessHeap(), 0, Password);
1296
1297 return res;
1298 }
1299
1300
1301 static
1302 INT_PTR
1303 CALLBACK
1304 UnlockDialogProc(
1305 IN HWND hwndDlg,
1306 IN UINT uMsg,
1307 IN WPARAM wParam,
1308 IN LPARAM lParam)
1309 {
1310 PDLG_DATA pDlgData;
1311 INT result = WLX_SAS_ACTION_NONE;
1312
1313 pDlgData = (PDLG_DATA)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
1314
1315 switch (uMsg)
1316 {
1317 case WM_INITDIALOG:
1318 {
1319 pDlgData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DLG_DATA));
1320 if (pDlgData == NULL)
1321 return FALSE;
1322
1323 SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)pDlgData);
1324
1325 pDlgData->pgContext = (PGINA_CONTEXT)lParam;
1326
1327 SetWelcomeText(hwndDlg);
1328
1329 SetLockMessage(hwndDlg, IDC_UNLOCK_MESSAGE, pDlgData->pgContext);
1330
1331 SetDlgItemTextW(hwndDlg, IDC_UNLOCK_USERNAME, pDlgData->pgContext->UserName);
1332 SetFocus(GetDlgItem(hwndDlg, IDC_UNLOCK_PASSWORD));
1333
1334 if (pDlgData->pgContext->bDisableCAD)
1335 EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), FALSE);
1336
1337 /* Load the logo bitmap */
1338 pDlgData->hBitmap = LoadImageW(pDlgData->pgContext->hDllInstance, MAKEINTRESOURCEW(IDI_ROSLOGO), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
1339 return TRUE;
1340 }
1341
1342 case WM_PAINT:
1343 {
1344 PAINTSTRUCT ps;
1345 if (pDlgData->hBitmap)
1346 {
1347 BeginPaint(hwndDlg, &ps);
1348 DrawStateW(ps.hdc, NULL, NULL, (LPARAM)pDlgData->hBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);
1349 EndPaint(hwndDlg, &ps);
1350 }
1351 return TRUE;
1352 }
1353 case WM_DESTROY:
1354 DeleteObject(pDlgData->hBitmap);
1355 HeapFree(GetProcessHeap(), 0, pDlgData);
1356 return TRUE;
1357
1358 case WM_COMMAND:
1359 switch (LOWORD(wParam))
1360 {
1361 case IDOK:
1362 if (DoUnlock(hwndDlg, pDlgData->pgContext, &result))
1363 EndDialog(hwndDlg, result);
1364 return TRUE;
1365
1366 case IDCANCEL:
1367 EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
1368 return TRUE;
1369 }
1370 break;
1371 }
1372
1373 return FALSE;
1374 }
1375
1376
1377 static INT
1378 GUILockedSAS(
1379 IN OUT PGINA_CONTEXT pgContext)
1380 {
1381 int result;
1382
1383 TRACE("GUILockedSAS()\n");
1384
1385 result = pgContext->pWlxFuncs->WlxDialogBoxParam(
1386 pgContext->hWlx,
1387 pgContext->hDllInstance,
1388 MAKEINTRESOURCEW(IDD_UNLOCK),
1389 GetDesktopWindow(),
1390 UnlockDialogProc,
1391 (LPARAM)pgContext);
1392 if (result >= WLX_SAS_ACTION_LOGON &&
1393 result <= WLX_SAS_ACTION_SWITCH_CONSOLE)
1394 {
1395 WARN("GUILockedSAS() returns 0x%x\n", result);
1396 return result;
1397 }
1398
1399 WARN("GUILockedSAS() failed (0x%x)\n", result);
1400 return WLX_SAS_ACTION_NONE;
1401 }
1402
1403
1404 static INT_PTR CALLBACK
1405 LockedDialogProc(
1406 IN HWND hwndDlg,
1407 IN UINT uMsg,
1408 IN WPARAM wParam,
1409 IN LPARAM lParam)
1410 {
1411 PDLG_DATA pDlgData;
1412
1413 pDlgData = (PDLG_DATA)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
1414
1415 switch (uMsg)
1416 {
1417 case WM_INITDIALOG:
1418 {
1419 pDlgData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DLG_DATA));
1420 if (pDlgData == NULL)
1421 return FALSE;
1422
1423 SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (LONG_PTR)pDlgData);
1424
1425 pDlgData->pgContext = (PGINA_CONTEXT)lParam;
1426
1427 /* Load the logo bitmap */
1428 pDlgData->hBitmap = LoadImageW(pDlgData->pgContext->hDllInstance, MAKEINTRESOURCEW(IDI_ROSLOGO), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
1429
1430 SetWelcomeText(hwndDlg);
1431
1432 SetLockMessage(hwndDlg, IDC_LOCKED_MESSAGE, pDlgData->pgContext);
1433 return TRUE;
1434 }
1435 case WM_PAINT:
1436 {
1437 PAINTSTRUCT ps;
1438 if (pDlgData->hBitmap)
1439 {
1440 BeginPaint(hwndDlg, &ps);
1441 DrawStateW(ps.hdc, NULL, NULL, (LPARAM)pDlgData->hBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);
1442 EndPaint(hwndDlg, &ps);
1443 }
1444 return TRUE;
1445 }
1446 case WM_DESTROY:
1447 {
1448 DeleteObject(pDlgData->hBitmap);
1449 HeapFree(GetProcessHeap(), 0, pDlgData);
1450 return TRUE;
1451 }
1452 }
1453
1454 return FALSE;
1455 }
1456
1457
1458 static VOID
1459 GUIDisplayLockedNotice(
1460 IN OUT PGINA_CONTEXT pgContext)
1461 {
1462 TRACE("GUIdisplayLockedNotice()\n");
1463
1464 pgContext->pWlxFuncs->WlxDialogBoxParam(
1465 pgContext->hWlx,
1466 pgContext->hDllInstance,
1467 MAKEINTRESOURCEW(IDD_LOCKED),
1468 GetDesktopWindow(),
1469 LockedDialogProc,
1470 (LPARAM)pgContext);
1471 }
1472
1473 GINA_UI GinaGraphicalUI = {
1474 GUIInitialize,
1475 GUIDisplayStatusMessage,
1476 GUIRemoveStatusMessage,
1477 GUIDisplaySASNotice,
1478 GUILoggedOnSAS,
1479 GUILoggedOutSAS,
1480 GUILockedSAS,
1481 GUIDisplayLockedNotice,
1482 };