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