xref: /reactos/dll/win32/msgina/gui.c (revision 45b08ed3)
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     /* Get the path of userinit */
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 };
1475