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