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