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