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