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