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