xref: /reactos/dll/win32/msgina/gui.c (revision cc439606)
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 };
1483