xref: /reactos/base/system/winlogon/wlx.c (revision 4561998a)
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 VOID
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); // FIXME: Must use restricted Winlogon-only security!!
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     SetWindowStationUser(Session->InteractiveWindowStation,
1308                          &LuidNone, NULL, 0);
1309 
1310     ret = TRUE;
1311 
1312 cleanup:
1313     if (!ret)
1314     {
1315         if (Session->ApplicationDesktop)
1316         {
1317             CloseDesktop(Session->ApplicationDesktop);
1318             Session->ApplicationDesktop = NULL;
1319         }
1320         if (Session->WinlogonDesktop)
1321         {
1322             CloseDesktop(Session->WinlogonDesktop);
1323             Session->WinlogonDesktop = NULL;
1324         }
1325         if (Session->ScreenSaverDesktop)
1326         {
1327             CloseDesktop(Session->ScreenSaverDesktop);
1328             Session->ScreenSaverDesktop = NULL;
1329         }
1330         if (Session->InteractiveWindowStation)
1331         {
1332             CloseWindowStation(Session->InteractiveWindowStation);
1333             Session->InteractiveWindowStation = NULL;
1334         }
1335     }
1336     HeapFree(GetProcessHeap(), 0, pDefaultAcl);
1337     HeapFree(GetProcessHeap(), 0, pUserDesktopAcl);
1338     return ret;
1339 }
1340