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