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