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