[WINLOGON] Close all dialog boxes on SAS
[reactos.git] / base / system / winlogon / wlx.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Winlogon
4 * FILE: base/system/winlogon/wlx.c
5 * PURPOSE: Logon
6 * PROGRAMMERS: Thomas Weidenmueller (w3seek@users.sourceforge.net)
7 * Ge van Geldorp (gvg@reactos.com)
8 * Hervé Poussineau (hpoussin@reactos.org)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include "winlogon.h"
14
15 #define DESKTOP_ALL (DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW | \
16 DESKTOP_CREATEMENU | DESKTOP_HOOKCONTROL | DESKTOP_JOURNALRECORD | \
17 DESKTOP_JOURNALPLAYBACK | DESKTOP_ENUMERATE | DESKTOP_WRITEOBJECTS | \
18 DESKTOP_SWITCHDESKTOP | STANDARD_RIGHTS_REQUIRED)
19
20 #define WINSTA_ALL (WINSTA_ENUMDESKTOPS | WINSTA_READATTRIBUTES | \
21 WINSTA_ACCESSCLIPBOARD | WINSTA_CREATEDESKTOP | \
22 WINSTA_WRITEATTRIBUTES | WINSTA_ACCESSGLOBALATOMS | \
23 WINSTA_EXITWINDOWS | WINSTA_ENUMERATE | WINSTA_READSCREEN | \
24 STANDARD_RIGHTS_REQUIRED)
25
26 #define GENERIC_ACCESS (GENERIC_READ | GENERIC_WRITE | \
27 GENERIC_EXECUTE | GENERIC_ALL)
28
29 typedef struct _DIALOG_LIST_ENTRY
30 {
31 LIST_ENTRY Entry;
32 HWND hWnd;
33 DLGPROC DlgProc;
34 LPARAM lParam;
35 } DIALOG_LIST_ENTRY, *PDIALOG_LIST_ENTRY;
36
37 /* GLOBALS ******************************************************************/
38
39 //static UINT_PTR IdTimer;
40 static LIST_ENTRY DialogListHead;
41
42 /* FUNCTIONS ****************************************************************/
43
44 VOID
45 InitDialogListHead(VOID)
46 {
47 InitializeListHead(&DialogListHead);
48 }
49
50
51 static
52 PDIALOG_LIST_ENTRY
53 AddDialogListEntry(VOID)
54 {
55 PDIALOG_LIST_ENTRY ListEntry;
56
57 ListEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DIALOG_LIST_ENTRY));
58 if (ListEntry == NULL)
59 return NULL;
60
61 TRACE("Add entry %p\n", ListEntry);
62
63 InsertHeadList(&DialogListHead,
64 &ListEntry->Entry);
65
66 return ListEntry;
67 }
68
69
70 static
71 VOID
72 RemoveDialogListEntry(PDIALOG_LIST_ENTRY ListEntry)
73 {
74 TRACE("Remove entry %p\n", ListEntry);
75
76 RemoveEntryList(&ListEntry->Entry);
77 RtlFreeHeap(RtlGetProcessHeap(), 0, ListEntry);
78 }
79
80
81 static
82 PDIALOG_LIST_ENTRY
83 GetDialogListEntry(HWND hwndDlg)
84 {
85 PDIALOG_LIST_ENTRY Current;
86 PLIST_ENTRY ListEntry;
87
88 ListEntry = DialogListHead.Flink;
89 while (ListEntry != &DialogListHead)
90 {
91 Current = CONTAINING_RECORD(ListEntry,
92 DIALOG_LIST_ENTRY,
93 Entry);
94 if (Current->hWnd == hwndDlg)
95 {
96 TRACE("Found entry: %p\n", Current);
97 return Current;
98 }
99
100 ListEntry = ListEntry->Flink;
101 }
102
103 TRACE("Found no entry!\n");
104 return NULL;
105 }
106
107
108 HWND
109 CloseAllDialogWindows(VOID)
110 {
111 PDIALOG_LIST_ENTRY Current;
112 PLIST_ENTRY ListEntry;
113
114 ListEntry = DialogListHead.Flink;
115 while (ListEntry != &DialogListHead)
116 {
117 Current = CONTAINING_RECORD(ListEntry,
118 DIALOG_LIST_ENTRY,
119 Entry);
120
121 PostMessage(Current->hWnd, WLX_WM_SAS, 0, 0);
122
123 ListEntry = ListEntry->Flink;
124 }
125 }
126
127
128 static
129 INT_PTR
130 CALLBACK
131 DefaultWlxWindowProc(
132 IN HWND hwndDlg,
133 IN UINT uMsg,
134 IN WPARAM wParam,
135 IN LPARAM lParam)
136 {
137 PDIALOG_LIST_ENTRY ListEntry;
138 INT_PTR ret;
139
140 if (uMsg == WM_INITDIALOG)
141 {
142 ListEntry = (PDIALOG_LIST_ENTRY)lParam;
143
144 TRACE("Set dialog handle: %p\n", hwndDlg);
145 ListEntry->hWnd = hwndDlg;
146 lParam = ListEntry->lParam;
147 // SetTopTimeout(hWnd);
148 }
149 else
150 {
151 ListEntry = GetDialogListEntry(hwndDlg);
152 if (ListEntry == NULL)
153 return FALSE;
154 }
155
156 if (uMsg == WLX_WM_SAS)
157 {
158 EndDialog(hwndDlg, WLX_DLG_SAS);
159 return 0;
160 }
161
162 ret = ListEntry->DlgProc(hwndDlg, uMsg, wParam, lParam);
163
164 return ret;
165
166 /*
167 if (uMsg == WM_TIMER && (UINT_PTR)wParam == IdTimer)
168 {
169 EndDialog(hwndDlg, -1);
170 KillTimer(hwndDlg, IdTimer);
171 return TRUE;
172 }
173 else if (uMsg == WM_INITDIALOG)
174 {
175 IdTimer = SetTimer(hwndDlg, 0, WLSession->DialogTimeout * 1000, NULL);
176 return PreviousWindowProc(hwndDlg, uMsg, wParam, lParam);
177 }
178 else if (uMsg == WM_NCDESTROY)
179 {
180 BOOL ret;
181 ret = PreviousWindowProc(hwndDlg, uMsg, wParam, lParam);
182 PreviousWindowProc = NULL;
183 return ret;
184 }
185 else
186 {
187 return PreviousWindowProc(hwndDlg, uMsg, wParam, lParam);
188 }
189 */
190 }
191
192 /*
193 * @implemented
194 */
195 VOID
196 WINAPI
197 WlxUseCtrlAltDel(
198 HANDLE hWlx)
199 {
200 ULONG_PTR OldValue;
201
202 TRACE("WlxUseCtrlAltDel()\n");
203
204 WlxSetOption(hWlx, WLX_OPTION_USE_CTRL_ALT_DEL, TRUE, &OldValue);
205 }
206
207 /*
208 * @implemented
209 */
210 VOID
211 WINAPI
212 WlxSetContextPointer(
213 HANDLE hWlx,
214 PVOID pWlxContext)
215 {
216 ULONG_PTR OldValue;
217
218 TRACE("WlxSetContextPointer(%p)\n", pWlxContext);
219
220 WlxSetOption(hWlx, WLX_OPTION_CONTEXT_POINTER, (ULONG_PTR)pWlxContext, &OldValue);
221 }
222
223 /*
224 * @implemented
225 */
226 VOID
227 WINAPI
228 WlxSasNotify(
229 HANDLE hWlx,
230 DWORD dwSasType)
231 {
232 PWLSESSION Session = (PWLSESSION)hWlx;
233
234 TRACE("WlxSasNotify(0x%lx)\n", dwSasType);
235
236 if (dwSasType == WLX_SAS_TYPE_CTRL_ALT_DEL || dwSasType > WLX_SAS_TYPE_MAX_MSFT_VALUE)
237 PostMessageW(Session->SASWindow, WLX_WM_SAS, dwSasType, 0);
238 }
239
240 /*
241 * @implemented
242 */
243 BOOL
244 WINAPI
245 WlxSetTimeout(
246 HANDLE hWlx,
247 DWORD Timeout)
248 {
249 PWLSESSION Session = (PWLSESSION)hWlx;
250
251 TRACE("WlxSetTimeout(%lu)\n", Timeout);
252
253 Session->DialogTimeout = Timeout;
254 return TRUE;
255 }
256
257 /*
258 * @unimplemented
259 */
260 int
261 WINAPI
262 WlxAssignShellProtection(
263 HANDLE hWlx,
264 HANDLE hToken,
265 HANDLE hProcess,
266 HANDLE hThread)
267 {
268 UNREFERENCED_PARAMETER(hWlx);
269 UNREFERENCED_PARAMETER(hToken);
270 UNREFERENCED_PARAMETER(hProcess);
271 UNREFERENCED_PARAMETER(hThread);
272
273 UNIMPLEMENTED;
274 return 0;
275 }
276
277 /*
278 * @implemented
279 */
280 int
281 WINAPI
282 WlxMessageBox(
283 HANDLE hWlx,
284 HWND hwndOwner,
285 LPWSTR lpszText,
286 LPWSTR lpszTitle,
287 UINT fuStyle)
288 {
289 UNREFERENCED_PARAMETER(hWlx);
290
291 TRACE("WlxMessageBox()\n");
292 /* FIXME: Provide a custom window proc to be able to handle timeout */
293 return MessageBoxW(hwndOwner, lpszText, lpszTitle, fuStyle);
294 }
295
296 /*
297 * @implemented
298 */
299 int
300 WINAPI
301 WlxDialogBox(
302 HANDLE hWlx,
303 HANDLE hInst,
304 LPWSTR lpszTemplate,
305 HWND hwndOwner,
306 DLGPROC dlgprc)
307 {
308 UNREFERENCED_PARAMETER(hWlx);
309
310 TRACE("WlxDialogBox()\n");
311
312 return (int)WlxDialogBoxParam(hWlx, hInst, lpszTemplate, hwndOwner, dlgprc, 0);
313 }
314
315 /*
316 * @implemented
317 */
318 int
319 WINAPI
320 WlxDialogBoxParam(
321 HANDLE hWlx,
322 HANDLE hInst,
323 LPWSTR lpszTemplate,
324 HWND hwndOwner,
325 DLGPROC dlgprc,
326 LPARAM dwInitParam)
327 {
328 PDIALOG_LIST_ENTRY ListEntry;
329 int ret;
330
331 UNREFERENCED_PARAMETER(hWlx);
332
333 TRACE("WlxDialogBoxParam()\n");
334
335 ListEntry = AddDialogListEntry();
336 if (ListEntry == NULL)
337 return -1;
338
339 ListEntry->DlgProc = dlgprc;
340 ListEntry->lParam = dwInitParam;
341
342 ret = (int)DialogBoxParamW(hInst, lpszTemplate, hwndOwner, DefaultWlxWindowProc, (LPARAM)ListEntry);
343
344 RemoveDialogListEntry(ListEntry);
345
346 return ret;
347 }
348
349 /*
350 * @implemented
351 */
352 int
353 WINAPI
354 WlxDialogBoxIndirect(
355 HANDLE hWlx,
356 HANDLE hInst,
357 LPCDLGTEMPLATE hDialogTemplate,
358 HWND hwndOwner,
359 DLGPROC dlgprc)
360 {
361 UNREFERENCED_PARAMETER(hWlx);
362
363 TRACE("WlxDialogBoxIndirect()\n");
364
365 return (int)WlxDialogBoxIndirectParam(hWlx, hInst, hDialogTemplate, hwndOwner, dlgprc, 0);
366 }
367
368 /*
369 * @implemented
370 */
371 int
372 WINAPI
373 WlxDialogBoxIndirectParam(
374 HANDLE hWlx,
375 HANDLE hInst,
376 LPCDLGTEMPLATE hDialogTemplate,
377 HWND hwndOwner,
378 DLGPROC dlgprc,
379 LPARAM dwInitParam)
380 {
381 PDIALOG_LIST_ENTRY ListEntry;
382 int ret;
383
384 UNREFERENCED_PARAMETER(hWlx);
385
386 TRACE("WlxDialogBoxIndirectParam()\n");
387
388 ListEntry = AddDialogListEntry();
389 if (ListEntry == NULL)
390 return -1;
391
392 ListEntry->DlgProc = dlgprc;
393 ListEntry->lParam = dwInitParam;
394
395 ret = (int)DialogBoxIndirectParamW(hInst, hDialogTemplate, hwndOwner, DefaultWlxWindowProc, (LPARAM)ListEntry);
396
397 RemoveDialogListEntry(ListEntry);
398
399 return ret;
400 }
401
402 /*
403 * @implemented
404 */
405 int
406 WINAPI
407 WlxSwitchDesktopToUser(
408 HANDLE hWlx)
409 {
410 PWLSESSION Session = (PWLSESSION)hWlx;
411
412 TRACE("WlxSwitchDesktopToUser()\n");
413
414 return (int)SwitchDesktop(Session->ApplicationDesktop);
415 }
416
417 /*
418 * @implemented
419 */
420 int
421 WINAPI
422 WlxSwitchDesktopToWinlogon(
423 HANDLE hWlx)
424 {
425 PWLSESSION Session = (PWLSESSION)hWlx;
426
427 TRACE("WlxSwitchDesktopToWinlogon()\n");
428
429 return (int)SwitchDesktop(Session->WinlogonDesktop);
430 }
431
432 /*
433 * @unimplemented
434 */
435 int
436 WINAPI
437 WlxChangePasswordNotify(
438 HANDLE hWlx,
439 PWLX_MPR_NOTIFY_INFO pMprInfo,
440 DWORD dwChangeInfo)
441 {
442 UNREFERENCED_PARAMETER(hWlx);
443 UNREFERENCED_PARAMETER(pMprInfo);
444 UNREFERENCED_PARAMETER(dwChangeInfo);
445
446 UNIMPLEMENTED;
447 return 0;
448 }
449
450 /*
451 * @unimplemented
452 */
453 BOOL
454 WINAPI
455 WlxGetSourceDesktop(
456 HANDLE hWlx,
457 PWLX_DESKTOP* ppDesktop)
458 {
459 UNREFERENCED_PARAMETER(hWlx);
460 UNREFERENCED_PARAMETER(ppDesktop);
461
462 UNIMPLEMENTED;
463 return FALSE;
464 }
465
466 /*
467 * @unimplemented
468 */
469 BOOL
470 WINAPI
471 WlxSetReturnDesktop(
472 HANDLE hWlx,
473 PWLX_DESKTOP pDesktop)
474 {
475 UNREFERENCED_PARAMETER(hWlx);
476 UNREFERENCED_PARAMETER(pDesktop);
477
478 UNIMPLEMENTED;
479 return FALSE;
480 }
481
482 /*
483 * @unimplemented
484 */
485 BOOL
486 WINAPI
487 WlxCreateUserDesktop(
488 HANDLE hWlx,
489 HANDLE hToken,
490 DWORD Flags,
491 PWSTR pszDesktopName,
492 PWLX_DESKTOP* ppDesktop)
493 {
494 UNREFERENCED_PARAMETER(hWlx);
495 UNREFERENCED_PARAMETER(hToken);
496 UNREFERENCED_PARAMETER(Flags);
497 UNREFERENCED_PARAMETER(pszDesktopName);
498 UNREFERENCED_PARAMETER(ppDesktop);
499
500 UNIMPLEMENTED;
501 return FALSE;
502 }
503
504 /*
505 * @unimplemented
506 */
507 int
508 WINAPI
509 WlxChangePasswordNotifyEx(
510 HANDLE hWlx,
511 PWLX_MPR_NOTIFY_INFO pMprInfo,
512 DWORD dwChangeInfo,
513 PWSTR ProviderName,
514 PVOID Reserved)
515 {
516 UNREFERENCED_PARAMETER(hWlx);
517 UNREFERENCED_PARAMETER(pMprInfo);
518 UNREFERENCED_PARAMETER(dwChangeInfo);
519 UNREFERENCED_PARAMETER(ProviderName);
520 UNREFERENCED_PARAMETER(Reserved);
521
522 UNIMPLEMENTED;
523 return 0;
524 }
525
526 /*
527 * @unimplemented
528 */
529 BOOL
530 WINAPI
531 WlxCloseUserDesktop(
532 HANDLE hWlx,
533 PWLX_DESKTOP pDesktop,
534 HANDLE hToken)
535 {
536 UNREFERENCED_PARAMETER(hWlx);
537 UNREFERENCED_PARAMETER(pDesktop);
538 UNREFERENCED_PARAMETER(hToken);
539
540 UNIMPLEMENTED;
541 return FALSE;
542 }
543
544 /*
545 * @implemented
546 */
547 BOOL
548 WINAPI
549 WlxSetOption(
550 HANDLE hWlx,
551 DWORD Option,
552 ULONG_PTR Value,
553 ULONG_PTR* OldValue)
554 {
555 PWLSESSION Session = (PWLSESSION)hWlx;
556
557 TRACE("WlxSetOption(%lu)\n", Option);
558
559 switch (Option)
560 {
561 case WLX_OPTION_USE_CTRL_ALT_DEL:
562 *OldValue = (ULONG_PTR)Session->Gina.UseCtrlAltDelete;
563 Session->Gina.UseCtrlAltDelete = (BOOL)Value;
564 return TRUE;
565 case WLX_OPTION_CONTEXT_POINTER:
566 *OldValue = (ULONG_PTR)Session->Gina.Context;
567 Session->Gina.Context = (PVOID)Value;
568 return TRUE;
569 case WLX_OPTION_USE_SMART_CARD:
570 UNIMPLEMENTED;
571 return FALSE;
572 }
573
574 return FALSE;
575 }
576
577 /*
578 * @implemented
579 */
580 BOOL
581 WINAPI
582 WlxGetOption(
583 HANDLE hWlx,
584 DWORD Option,
585 ULONG_PTR* Value)
586 {
587 PWLSESSION Session = (PWLSESSION)hWlx;
588
589 TRACE("WlxGetOption(%lu)\n", Option);
590
591 switch (Option)
592 {
593 case WLX_OPTION_USE_CTRL_ALT_DEL:
594 *Value = (ULONG_PTR)Session->Gina.UseCtrlAltDelete;
595 return TRUE;
596 case WLX_OPTION_CONTEXT_POINTER:
597 {
598 *Value = (ULONG_PTR)Session->Gina.Context;
599 return TRUE;
600 }
601 case WLX_OPTION_USE_SMART_CARD:
602 case WLX_OPTION_SMART_CARD_PRESENT:
603 case WLX_OPTION_SMART_CARD_INFO:
604 UNIMPLEMENTED;
605 return FALSE;
606 case WLX_OPTION_DISPATCH_TABLE_SIZE:
607 {
608 switch (Session->Gina.Version)
609 {
610 case WLX_VERSION_1_0:
611 *Value = sizeof(WLX_DISPATCH_VERSION_1_0);
612 break;
613 case WLX_VERSION_1_1:
614 *Value = sizeof(WLX_DISPATCH_VERSION_1_1);
615 break;
616 case WLX_VERSION_1_2:
617 *Value = sizeof(WLX_DISPATCH_VERSION_1_2);
618 break;
619 case WLX_VERSION_1_3:
620 *Value = sizeof(WLX_DISPATCH_VERSION_1_3);
621 break;
622 case WLX_VERSION_1_4:
623 *Value = sizeof(WLX_DISPATCH_VERSION_1_4);
624 break;
625 default:
626 return FALSE;
627 }
628 return TRUE;
629 }
630 }
631
632 return FALSE;
633 }
634
635 /*
636 * @unimplemented
637 */
638 VOID
639 WINAPI
640 WlxWin31Migrate(
641 HANDLE hWlx)
642 {
643 UNREFERENCED_PARAMETER(hWlx);
644
645 UNIMPLEMENTED;
646 }
647
648 /*
649 * @unimplemented
650 */
651 BOOL
652 WINAPI
653 WlxQueryClientCredentials(
654 PWLX_CLIENT_CREDENTIALS_INFO_V1_0 pCred)
655 {
656 UNREFERENCED_PARAMETER(pCred);
657
658 UNIMPLEMENTED;
659 return FALSE;
660 }
661
662 /*
663 * @unimplemented
664 */
665 BOOL
666 WINAPI
667 WlxQueryInetConnectorCredentials(
668 PWLX_CLIENT_CREDENTIALS_INFO_V1_0 pCred)
669 {
670 UNREFERENCED_PARAMETER(pCred);
671
672 UNIMPLEMENTED;
673 return FALSE;
674 }
675
676 /*
677 * @unimplemented
678 */
679 BOOL
680 WINAPI
681 WlxDisconnect(VOID)
682 {
683 UNIMPLEMENTED;
684 return FALSE;
685 }
686
687 /*
688 * @unimplemented
689 */
690 DWORD
691 WINAPI
692 WlxQueryTerminalServicesData(
693 HANDLE hWlx,
694 PWLX_TERMINAL_SERVICES_DATA pTSData,
695 WCHAR* UserName,
696 WCHAR* Domain)
697 {
698 UNREFERENCED_PARAMETER(hWlx);
699 UNREFERENCED_PARAMETER(pTSData);
700 UNREFERENCED_PARAMETER(UserName);
701 UNREFERENCED_PARAMETER(Domain);
702
703 UNIMPLEMENTED;
704 return 0;
705 }
706
707 /*
708 * @unimplemented
709 */
710 DWORD
711 WINAPI
712 WlxQueryConsoleSwitchCredentials(
713 PWLX_CONSOLESWITCH_CREDENTIALS_INFO_V1_0 pCred)
714 {
715 UNREFERENCED_PARAMETER(pCred);
716
717 UNIMPLEMENTED;
718 return 0;
719 }
720
721 /*
722 * @unimplemented
723 */
724 BOOL
725 WINAPI
726 WlxQueryTsLogonCredentials(
727 PWLX_CLIENT_CREDENTIALS_INFO_V2_0 pCred)
728 {
729 UNREFERENCED_PARAMETER(pCred);
730
731 UNIMPLEMENTED;
732 return FALSE;
733 }
734
735 static
736 WLX_DISPATCH_VERSION_1_4 FunctionTable = {
737 WlxUseCtrlAltDel,
738 WlxSetContextPointer,
739 WlxSasNotify,
740 WlxSetTimeout,
741 WlxAssignShellProtection,
742 WlxMessageBox,
743 WlxDialogBox,
744 WlxDialogBoxParam,
745 WlxDialogBoxIndirect,
746 WlxDialogBoxIndirectParam,
747 WlxSwitchDesktopToUser,
748 WlxSwitchDesktopToWinlogon,
749 WlxChangePasswordNotify,
750 WlxGetSourceDesktop,
751 WlxSetReturnDesktop,
752 WlxCreateUserDesktop,
753 WlxChangePasswordNotifyEx,
754 WlxCloseUserDesktop,
755 WlxSetOption,
756 WlxGetOption,
757 WlxWin31Migrate,
758 WlxQueryClientCredentials,
759 WlxQueryInetConnectorCredentials,
760 WlxDisconnect,
761 WlxQueryTerminalServicesData,
762 WlxQueryConsoleSwitchCredentials,
763 WlxQueryTsLogonCredentials
764 };
765
766 /******************************************************************************/
767
768 static
769 BOOL
770 GetGinaPath(
771 OUT LPWSTR Path,
772 IN DWORD Len)
773 {
774 LONG Status;
775 DWORD Type, Size;
776 HKEY hKey;
777
778 Status = RegOpenKeyExW(
779 HKEY_LOCAL_MACHINE,
780 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
781 0,
782 KEY_QUERY_VALUE,
783 &hKey);
784 if (Status != ERROR_SUCCESS)
785 {
786 /* Default value */
787 wcsncpy(Path, L"msgina.dll", Len);
788 return TRUE;
789 }
790
791 Size = Len * sizeof(WCHAR);
792 Status = RegQueryValueExW(
793 hKey,
794 L"GinaDLL",
795 NULL,
796 &Type,
797 (LPBYTE)Path,
798 &Size);
799 if (Status != ERROR_SUCCESS || Type != REG_SZ || Size == 0)
800 wcsncpy(Path, L"msgina.dll", Len);
801 RegCloseKey(hKey);
802 return TRUE;
803 }
804
805 static
806 BOOL
807 WINAPI
808 DefaultWlxScreenSaverNotify(
809 IN PVOID pWlxContext,
810 IN OUT BOOL *pSecure)
811 {
812 if (*pSecure)
813 *pSecure = WLSession->Gina.Functions.WlxIsLogoffOk(pWlxContext);
814 return TRUE;
815 }
816
817 static
818 BOOL
819 LoadGina(
820 IN OUT PGINAFUNCTIONS Functions,
821 OUT DWORD *DllVersion,
822 OUT HMODULE *GinaInstance)
823 {
824 HMODULE hGina = NULL;
825 WCHAR GinaDll[MAX_PATH + 1];
826 BOOL ret = FALSE;
827
828 GinaDll[0] = '\0';
829 if (!GetGinaPath(GinaDll, MAX_PATH))
830 goto cleanup;
831 /* Terminate string */
832 GinaDll[MAX_PATH] = '\0';
833
834 hGina = LoadLibraryW(GinaDll);
835 if (!hGina)
836 goto cleanup;
837
838 Functions->WlxNegotiate = (PFWLXNEGOTIATE)GetProcAddress(hGina, "WlxNegotiate");
839 Functions->WlxInitialize = (PFWLXINITIALIZE)GetProcAddress(hGina, "WlxInitialize");
840
841 if (!Functions->WlxInitialize)
842 goto cleanup;
843
844 if (!Functions->WlxNegotiate)
845 {
846 /* Assume current version */
847 *DllVersion = WLX_CURRENT_VERSION;
848 }
849 else
850 {
851 TRACE("About to negotiate with Gina %S. Winlogon uses version %x\n",
852 GinaDll, WLX_CURRENT_VERSION);
853 if (!Functions->WlxNegotiate(WLX_CURRENT_VERSION, DllVersion))
854 goto cleanup;
855 }
856
857 TRACE("Gina uses WLX_VERSION %lx\n", *DllVersion);
858
859 if (*DllVersion >= WLX_VERSION_1_0)
860 {
861 Functions->WlxActivateUserShell = (PFWLXACTIVATEUSERSHELL)GetProcAddress(hGina, "WlxActivateUserShell");
862 if (!Functions->WlxActivateUserShell) goto cleanup;
863 Functions->WlxDisplayLockedNotice = (PFWLXDISPLAYLOCKEDNOTICE)GetProcAddress(hGina, "WlxDisplayLockedNotice");
864 if (!Functions->WlxDisplayLockedNotice) goto cleanup;
865 Functions->WlxDisplaySASNotice = (PFWLXDISPLAYSASNOTICE)GetProcAddress(hGina, "WlxDisplaySASNotice");
866 if (!Functions->WlxDisplaySASNotice) goto cleanup;
867 Functions->WlxIsLockOk = (PFWLXISLOCKOK)GetProcAddress(hGina, "WlxIsLockOk");
868 if (!Functions->WlxIsLockOk) goto cleanup;
869 Functions->WlxIsLogoffOk = (PFWLXISLOGOFFOK)GetProcAddress(hGina, "WlxIsLogoffOk");
870 if (!Functions->WlxIsLogoffOk) goto cleanup;
871 Functions->WlxLoggedOnSAS = (PFWLXLOGGEDONSAS)GetProcAddress(hGina, "WlxLoggedOnSAS");
872 if (!Functions->WlxLoggedOnSAS) goto cleanup;
873 Functions->WlxLoggedOutSAS = (PFWLXLOGGEDOUTSAS)GetProcAddress(hGina, "WlxLoggedOutSAS");
874 if (!Functions->WlxLoggedOutSAS) goto cleanup;
875 Functions->WlxLogoff = (PFWLXLOGOFF)GetProcAddress(hGina, "WlxLogoff");
876 if (!Functions->WlxLogoff) goto cleanup;
877 Functions->WlxShutdown = (PFWLXSHUTDOWN)GetProcAddress(hGina, "WlxShutdown");
878 if (!Functions->WlxShutdown) goto cleanup;
879 Functions->WlxWkstaLockedSAS = (PFWLXWKSTALOCKEDSAS)GetProcAddress(hGina, "WlxWkstaLockedSAS");
880 if (!Functions->WlxWkstaLockedSAS) goto cleanup;
881 }
882
883 if (*DllVersion >= WLX_VERSION_1_1)
884 {
885 Functions->WlxScreenSaverNotify = (PFWLXSCREENSAVERNOTIFY)GetProcAddress(hGina, "WlxScreenSaverNotify");
886 Functions->WlxStartApplication = (PFWLXSTARTAPPLICATION)GetProcAddress(hGina, "WlxStartApplication");
887 }
888
889 if (*DllVersion >= WLX_VERSION_1_3)
890 {
891 Functions->WlxDisplayStatusMessage = (PFWLXDISPLAYSTATUSMESSAGE)GetProcAddress(hGina, "WlxDisplayStatusMessage");
892 if (!Functions->WlxDisplayStatusMessage) goto cleanup;
893 Functions->WlxGetStatusMessage = (PFWLXGETSTATUSMESSAGE)GetProcAddress(hGina, "WlxGetStatusMessage");
894 if (!Functions->WlxGetStatusMessage) goto cleanup;
895 Functions->WlxNetworkProviderLoad = (PFWLXNETWORKPROVIDERLOAD)GetProcAddress(hGina, "WlxNetworkProviderLoad");
896 if (!Functions->WlxNetworkProviderLoad) goto cleanup;
897 Functions->WlxRemoveStatusMessage = (PFWLXREMOVESTATUSMESSAGE)GetProcAddress(hGina, "WlxRemoveStatusMessage");
898 if (!Functions->WlxRemoveStatusMessage) goto cleanup;
899 }
900
901 /* Provide some default functions */
902 if (!Functions->WlxScreenSaverNotify)
903 Functions->WlxScreenSaverNotify = DefaultWlxScreenSaverNotify;
904
905 ret = TRUE;
906
907 cleanup:
908 if (!ret)
909 {
910 if (hGina)
911 FreeLibrary(hGina);
912 }
913 else
914 *GinaInstance = hGina;
915 return ret;
916 }
917
918 BOOL
919 GinaInit(
920 IN OUT PWLSESSION Session)
921 {
922 DWORD GinaDllVersion;
923
924 if (!LoadGina(&Session->Gina.Functions, &GinaDllVersion, &Session->Gina.hDllInstance))
925 return FALSE;
926
927 Session->Gina.Context = NULL;
928 Session->Gina.Version = GinaDllVersion;
929 Session->Gina.UseCtrlAltDelete = FALSE;
930 Session->SuppressStatus = FALSE;
931
932 TRACE("Calling WlxInitialize(\"%S\")\n", Session->InteractiveWindowStationName);
933 return Session->Gina.Functions.WlxInitialize(
934 Session->InteractiveWindowStationName,
935 (HANDLE)Session,
936 NULL,
937 (PVOID)&FunctionTable,
938 &Session->Gina.Context);
939 }
940
941 BOOL
942 AddAceToWindowStation(
943 IN HWINSTA WinSta,
944 IN PSID Sid)
945 {
946 DWORD AclSize;
947 SECURITY_INFORMATION SecurityInformation;
948 PACL pDefaultAcl = NULL;
949 PSECURITY_DESCRIPTOR WinstaSd = NULL;
950 PACCESS_ALLOWED_ACE Ace = NULL;
951 BOOL Ret = FALSE;
952
953 /* Allocate space for an ACL */
954 AclSize = sizeof(ACL)
955 + 2 * (FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(Sid));
956 pDefaultAcl = HeapAlloc(GetProcessHeap(), 0, AclSize);
957 if (!pDefaultAcl)
958 {
959 ERR("WL: HeapAlloc() failed\n");
960 goto cleanup;
961 }
962
963 /* Initialize it */
964 if (!InitializeAcl(pDefaultAcl, AclSize, ACL_REVISION))
965 {
966 ERR("WL: InitializeAcl() failed (error %lu)\n", GetLastError());
967 goto cleanup;
968 }
969
970 /* Initialize new security descriptor */
971 WinstaSd = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
972 if (!InitializeSecurityDescriptor(WinstaSd, SECURITY_DESCRIPTOR_REVISION))
973 {
974 ERR("WL: InitializeSecurityDescriptor() failed (error %lu)\n", GetLastError());
975 goto cleanup;
976 }
977
978 /* Allocate memory for access allowed ACE */
979 Ace = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACCESS_ALLOWED_ACE)+
980 GetLengthSid(Sid) - sizeof(DWORD));
981
982 /* Create the first ACE for the window station */
983 Ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
984 Ace->Header.AceFlags = CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE;
985 Ace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(Sid) - sizeof(DWORD);
986 Ace->Mask = GENERIC_ACCESS;
987
988 /* Copy the sid */
989 if (!CopySid(GetLengthSid(Sid), &Ace->SidStart, Sid))
990 {
991 ERR("WL: CopySid() failed (error %lu)\n", GetLastError());
992 goto cleanup;
993 }
994
995 /* Add the first ACE */
996 if (!AddAce(pDefaultAcl, ACL_REVISION, MAXDWORD, (LPVOID)Ace, Ace->Header.AceSize))
997 {
998 ERR("WL: AddAce() failed (error %lu)\n", GetLastError());
999 goto cleanup;
1000 }
1001
1002 /* Add the second ACE to the end of ACL */
1003 Ace->Header.AceFlags = NO_PROPAGATE_INHERIT_ACE;
1004 Ace->Mask = WINSTA_ALL;
1005 if (!AddAce(pDefaultAcl, ACL_REVISION, MAXDWORD, (LPVOID)Ace, Ace->Header.AceSize))
1006 {
1007 ERR("WL: AddAce() failed (error %lu)\n", GetLastError());
1008 goto cleanup;
1009 }
1010
1011 /* Add ACL to winsta's security descriptor */
1012 if (!SetSecurityDescriptorDacl(WinstaSd, TRUE, pDefaultAcl, FALSE))
1013 {
1014 ERR("WL: SetSecurityDescriptorDacl() failed (error %lu)\n", GetLastError());
1015 goto cleanup;
1016 }
1017
1018 /* Apply security to the window station */
1019 SecurityInformation = DACL_SECURITY_INFORMATION;
1020 if (!SetUserObjectSecurity(WinSta, &SecurityInformation, WinstaSd))
1021 {
1022 ERR("WL: SetUserObjectSecurity() failed (error %lu)\n", GetLastError());
1023 goto cleanup;
1024 }
1025
1026 /* Indicate success */
1027 Ret = TRUE;
1028
1029 cleanup:
1030 /* Free allocated stuff */
1031 if (pDefaultAcl) HeapFree(GetProcessHeap(), 0, pDefaultAcl);
1032 if (WinstaSd) HeapFree(GetProcessHeap(), 0, WinstaSd);
1033 if (Ace) HeapFree(GetProcessHeap(), 0, Ace);
1034
1035 return Ret;
1036 }
1037
1038 BOOL
1039 AddAceToDesktop(
1040 IN HDESK Desktop,
1041 IN PSID WinlogonSid,
1042 IN PSID UserSid)
1043 {
1044 DWORD AclSize;
1045 SECURITY_INFORMATION SecurityInformation;
1046 PACL Acl = NULL;
1047 PSECURITY_DESCRIPTOR DesktopSd = NULL;
1048 BOOL Ret = FALSE;
1049
1050 /* Allocate ACL */
1051 AclSize = sizeof(ACL)
1052 + FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(WinlogonSid);
1053
1054 /* Take user's sid into account */
1055 if (UserSid)
1056 AclSize += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(UserSid);
1057
1058 Acl = HeapAlloc(GetProcessHeap(), 0, AclSize);
1059 if (!Acl)
1060 {
1061 ERR("WL: HeapAlloc() failed\n");
1062 goto cleanup;
1063 }
1064
1065 /* Initialize ACL */
1066 if (!InitializeAcl(Acl, AclSize, ACL_REVISION))
1067 {
1068 ERR("WL: InitializeAcl() failed (error %lu)\n", GetLastError());
1069 goto cleanup;
1070 }
1071
1072 /* Add full desktop access ACE for winlogon */
1073 if (!AddAccessAllowedAce(Acl, ACL_REVISION, DESKTOP_ALL, WinlogonSid))
1074 {
1075 ERR("WL: AddAccessAllowedAce() failed (error %lu)\n", GetLastError());
1076 goto cleanup;
1077 }
1078
1079 /* Add full desktop access ACE for a user (if provided) */
1080 if (UserSid && !AddAccessAllowedAce(Acl, ACL_REVISION, DESKTOP_ALL, UserSid))
1081 {
1082 ERR("WL: AddAccessAllowedAce() failed (error %lu)\n", GetLastError());
1083 goto cleanup;
1084 }
1085
1086 /* Initialize new security descriptor */
1087 DesktopSd = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
1088 if (!InitializeSecurityDescriptor(DesktopSd, SECURITY_DESCRIPTOR_REVISION))
1089 {
1090 ERR("WL: InitializeSecurityDescriptor() failed (error %lu)\n", GetLastError());
1091 goto cleanup;
1092 }
1093
1094 /* Add ACL to the security descriptor */
1095 if (!SetSecurityDescriptorDacl(DesktopSd, TRUE, Acl, FALSE))
1096 {
1097 ERR("WL: SetSecurityDescriptorDacl() failed (error %lu)\n", GetLastError());
1098 goto cleanup;
1099 }
1100
1101 /* Apply security to the window station */
1102 SecurityInformation = DACL_SECURITY_INFORMATION;
1103 if (!SetUserObjectSecurity(Desktop, &SecurityInformation, DesktopSd))
1104 {
1105 ERR("WL: SetUserObjectSecurity() failed (error %lu)\n", GetLastError());
1106 goto cleanup;
1107 }
1108
1109 /* Indicate success */
1110 Ret = TRUE;
1111
1112 cleanup:
1113 /* Free allocated stuff */
1114 if (Acl) HeapFree(GetProcessHeap(), 0, Acl);
1115 if (DesktopSd) HeapFree(GetProcessHeap(), 0, DesktopSd);
1116
1117 return Ret;
1118 }
1119
1120 BOOL
1121 CreateWindowStationAndDesktops(
1122 IN OUT PWLSESSION Session)
1123 {
1124 BYTE LocalSystemBuffer[SECURITY_MAX_SID_SIZE];
1125 BYTE InteractiveBuffer[SECURITY_MAX_SID_SIZE];
1126 PSID pLocalSystemSid = (PSID)&LocalSystemBuffer;
1127 PSID pInteractiveSid = (PSID)InteractiveBuffer;
1128 DWORD SidSize, AclSize;
1129 PACL pDefaultAcl = NULL;
1130 PACL pUserDesktopAcl = NULL;
1131 SECURITY_DESCRIPTOR DefaultSecurityDescriptor;
1132 SECURITY_ATTRIBUTES DefaultSecurity;
1133 SECURITY_DESCRIPTOR UserDesktopSecurityDescriptor;
1134 SECURITY_ATTRIBUTES UserDesktopSecurity;
1135 BOOL ret = FALSE;
1136
1137 /*
1138 * Prepare information for ACLs we will apply
1139 */
1140 SidSize = SECURITY_MAX_SID_SIZE;
1141 if (!CreateWellKnownSid(WinLocalSystemSid, NULL, pLocalSystemSid, &SidSize))
1142 {
1143 ERR("WL: CreateWellKnownSid() failed (error %lu)\n", GetLastError());
1144 goto cleanup;
1145 }
1146 SidSize = SECURITY_MAX_SID_SIZE;
1147 if (!CreateWellKnownSid(WinInteractiveSid, NULL, pInteractiveSid, &SidSize))
1148 {
1149 ERR("WL: CreateWellKnownSid() failed (error %lu)\n", GetLastError());
1150 goto cleanup;
1151 }
1152
1153 AclSize = sizeof(ACL)
1154 + FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(pLocalSystemSid)
1155 + FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(pInteractiveSid);
1156 pDefaultAcl = HeapAlloc(GetProcessHeap(), 0, AclSize);
1157 pUserDesktopAcl = HeapAlloc(GetProcessHeap(), 0, AclSize);
1158 if (!pDefaultAcl || !pUserDesktopAcl)
1159 {
1160 ERR("WL: HeapAlloc() failed\n");
1161 goto cleanup;
1162 }
1163
1164 if (!InitializeAcl(pDefaultAcl, AclSize, ACL_REVISION)
1165 || !InitializeAcl(pUserDesktopAcl, AclSize, ACL_REVISION))
1166 {
1167 ERR("WL: InitializeAcl() failed (error %lu)\n", GetLastError());
1168 goto cleanup;
1169 }
1170
1171 /*
1172 * Create default ACL (window station, winlogon desktop, screen saver desktop)
1173 */
1174 if (!AddAccessAllowedAce(pDefaultAcl, ACL_REVISION, GENERIC_ALL, pLocalSystemSid)
1175 || !AddAccessAllowedAce(pDefaultAcl, ACL_REVISION, GENERIC_READ, pInteractiveSid))
1176 {
1177 ERR("WL: AddAccessAllowedAce() failed (error %lu)\n", GetLastError());
1178 goto cleanup;
1179 }
1180
1181 /*
1182 * Create the default security descriptor
1183 */
1184 if (!InitializeSecurityDescriptor(&DefaultSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION))
1185 {
1186 ERR("WL: InitializeSecurityDescriptor() failed (error %lu)\n", GetLastError());
1187 goto cleanup;
1188 }
1189
1190 if (!SetSecurityDescriptorDacl(&DefaultSecurityDescriptor, TRUE, pDefaultAcl, FALSE))
1191 {
1192 ERR("WL: SetSecurityDescriptorDacl() failed (error %lu)\n", GetLastError());
1193 goto cleanup;
1194 }
1195
1196 DefaultSecurity.nLength = sizeof(SECURITY_ATTRIBUTES);
1197 DefaultSecurity.lpSecurityDescriptor = &DefaultSecurityDescriptor;
1198 DefaultSecurity.bInheritHandle = TRUE;
1199
1200 /*
1201 * Create user desktop ACL
1202 */
1203 if (!AddAccessAllowedAce(pUserDesktopAcl, ACL_REVISION, GENERIC_ALL, pLocalSystemSid)
1204 || !AddAccessAllowedAce(pUserDesktopAcl, ACL_REVISION, GENERIC_ALL, pInteractiveSid))
1205 {
1206 ERR("WL: AddAccessAllowedAce() failed (error %lu)\n", GetLastError());
1207 goto cleanup;
1208 }
1209
1210 /*
1211 * Create the user desktop security descriptor
1212 */
1213 if (!InitializeSecurityDescriptor(&UserDesktopSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION))
1214 {
1215 ERR("WL: InitializeSecurityDescriptor() failed (error %lu)\n", GetLastError());
1216 goto cleanup;
1217 }
1218
1219 if (!SetSecurityDescriptorDacl(&UserDesktopSecurityDescriptor, TRUE, pUserDesktopAcl, FALSE))
1220 {
1221 ERR("WL: SetSecurityDescriptorDacl() failed (error %lu)\n", GetLastError());
1222 goto cleanup;
1223 }
1224
1225 UserDesktopSecurity.nLength = sizeof(SECURITY_ATTRIBUTES);
1226 UserDesktopSecurity.lpSecurityDescriptor = &UserDesktopSecurityDescriptor;
1227 UserDesktopSecurity.bInheritHandle = TRUE;
1228
1229 /*
1230 * Create the interactive window station
1231 */
1232 Session->InteractiveWindowStationName = L"WinSta0";
1233 Session->InteractiveWindowStation = CreateWindowStationW(
1234 Session->InteractiveWindowStationName,
1235 0,
1236 MAXIMUM_ALLOWED,
1237 &DefaultSecurity);
1238 if (!Session->InteractiveWindowStation)
1239 {
1240 ERR("WL: Failed to create window station (%lu)\n", GetLastError());
1241 goto cleanup;
1242 }
1243 if (!SetProcessWindowStation(Session->InteractiveWindowStation))
1244 {
1245 ERR("WL: SetProcessWindowStation() failed (error %lu)\n", GetLastError());
1246 goto cleanup;
1247 }
1248
1249 /*
1250 * Create the application desktop
1251 */
1252 Session->ApplicationDesktop = CreateDesktopW(
1253 L"Default",
1254 NULL,
1255 NULL,
1256 0, /* FIXME: Add DF_ALLOWOTHERACCOUNTHOOK flag? */
1257 MAXIMUM_ALLOWED,
1258 &UserDesktopSecurity);
1259 if (!Session->ApplicationDesktop)
1260 {
1261 ERR("WL: Failed to create Default desktop (%lu)\n", GetLastError());
1262 goto cleanup;
1263 }
1264
1265 /*
1266 * Create the winlogon desktop
1267 */
1268 Session->WinlogonDesktop = CreateDesktopW(
1269 L"Winlogon",
1270 NULL,
1271 NULL,
1272 0,
1273 MAXIMUM_ALLOWED,
1274 &DefaultSecurity);
1275 if (!Session->WinlogonDesktop)
1276 {
1277 ERR("WL: Failed to create Winlogon desktop (%lu)\n", GetLastError());
1278 goto cleanup;
1279 }
1280
1281 /*
1282 * Create the screen saver desktop
1283 */
1284 Session->ScreenSaverDesktop = CreateDesktopW(
1285 L"Screen-Saver",
1286 NULL,
1287 NULL,
1288 0,
1289 MAXIMUM_ALLOWED,
1290 &DefaultSecurity);
1291 if(!Session->ScreenSaverDesktop)
1292 {
1293 ERR("WL: Failed to create Screen-Saver desktop (%lu)\n", GetLastError());
1294 goto cleanup;
1295 }
1296
1297 /*
1298 * Switch to winlogon desktop
1299 */
1300 if (!SetThreadDesktop(Session->WinlogonDesktop) ||
1301 !SwitchDesktop(Session->WinlogonDesktop))
1302 {
1303 ERR("WL: Cannot switch to Winlogon desktop (%lu)\n", GetLastError());
1304 goto cleanup;
1305 }
1306
1307 ret = TRUE;
1308
1309 cleanup:
1310 if (!ret)
1311 {
1312 if (Session->ApplicationDesktop)
1313 {
1314 CloseDesktop(Session->ApplicationDesktop);
1315 Session->ApplicationDesktop = NULL;
1316 }
1317 if (Session->WinlogonDesktop)
1318 {
1319 CloseDesktop(Session->WinlogonDesktop);
1320 Session->WinlogonDesktop = NULL;
1321 }
1322 if (Session->ScreenSaverDesktop)
1323 {
1324 CloseDesktop(Session->ScreenSaverDesktop);
1325 Session->ScreenSaverDesktop = NULL;
1326 }
1327 if (Session->InteractiveWindowStation)
1328 {
1329 CloseWindowStation(Session->InteractiveWindowStation);
1330 Session->InteractiveWindowStation = NULL;
1331 }
1332 }
1333 HeapFree(GetProcessHeap(), 0, pDefaultAcl);
1334 HeapFree(GetProcessHeap(), 0, pUserDesktopAcl);
1335 return ret;
1336 }