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