7254b871709385113d60b6316ef47c814e444417
[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 * 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 };