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