1 /* 2 * ReactOS GINA 3 * Copyright (C) 2003-2004, 2006 ReactOS Team 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 */ 19 /* 20 * PROJECT: ReactOS msgina.dll 21 * FILE: dll/win32/msgina/msgina.c 22 * PURPOSE: ReactOS Logon GINA DLL 23 * PROGRAMMER: Thomas Weidenmueller (w3seek@users.sourceforge.net) 24 * Herv� Poussineau (hpoussin@reactos.org) 25 */ 26 27 #include "msgina.h" 28 29 #include <winsvc.h> 30 #include <userenv.h> 31 #include <ndk/sefuncs.h> 32 33 HINSTANCE hDllInstance; 34 35 extern GINA_UI GinaGraphicalUI; 36 extern GINA_UI GinaTextUI; 37 static PGINA_UI pGinaUI; 38 static SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY}; 39 static PSID AdminSid; 40 41 /* 42 * @implemented 43 */ 44 BOOL WINAPI 45 WlxNegotiate( 46 IN DWORD dwWinlogonVersion, 47 OUT PDWORD pdwDllVersion) 48 { 49 TRACE("WlxNegotiate(%lx, %p)\n", dwWinlogonVersion, pdwDllVersion); 50 51 if(!pdwDllVersion || (dwWinlogonVersion < WLX_VERSION_1_3)) 52 return FALSE; 53 54 *pdwDllVersion = WLX_VERSION_1_3; 55 56 return TRUE; 57 } 58 59 LONG 60 ReadRegSzValue( 61 IN HKEY hKey, 62 IN LPCWSTR pszValue, 63 OUT LPWSTR* pValue) 64 { 65 LONG rc; 66 DWORD dwType; 67 DWORD cbData = 0; 68 LPWSTR Value; 69 70 if (!pValue) 71 return ERROR_INVALID_PARAMETER; 72 73 *pValue = NULL; 74 rc = RegQueryValueExW(hKey, pszValue, NULL, &dwType, NULL, &cbData); 75 if (rc != ERROR_SUCCESS) 76 return rc; 77 if (dwType != REG_SZ) 78 return ERROR_FILE_NOT_FOUND; 79 Value = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR)); 80 if (!Value) 81 return ERROR_NOT_ENOUGH_MEMORY; 82 rc = RegQueryValueExW(hKey, pszValue, NULL, NULL, (LPBYTE)Value, &cbData); 83 if (rc != ERROR_SUCCESS) 84 { 85 HeapFree(GetProcessHeap(), 0, Value); 86 return rc; 87 } 88 /* NULL-terminate the string */ 89 Value[cbData / sizeof(WCHAR)] = '\0'; 90 91 *pValue = Value; 92 return ERROR_SUCCESS; 93 } 94 95 static LONG 96 ReadRegDwordValue( 97 IN HKEY hKey, 98 IN LPCWSTR pszValue, 99 OUT LPDWORD pValue) 100 { 101 LONG rc; 102 DWORD dwType; 103 DWORD cbData; 104 DWORD dwValue; 105 106 if (!pValue) 107 return ERROR_INVALID_PARAMETER; 108 109 cbData = sizeof(DWORD); 110 rc = RegQueryValueExW(hKey, pszValue, NULL, &dwType, (LPBYTE)&dwValue, &cbData); 111 if (rc == ERROR_SUCCESS && dwType == REG_DWORD) 112 *pValue = dwValue; 113 114 return ERROR_SUCCESS; 115 } 116 117 static VOID 118 ChooseGinaUI(VOID) 119 { 120 HKEY ControlKey = NULL; 121 LPWSTR SystemStartOptions = NULL; 122 LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */ 123 BOOL ConsoleBoot = FALSE; 124 LONG rc; 125 126 rc = RegOpenKeyExW( 127 HKEY_LOCAL_MACHINE, 128 L"SYSTEM\\CurrentControlSet\\Control", 129 0, 130 KEY_QUERY_VALUE, 131 &ControlKey); 132 133 rc = ReadRegSzValue(ControlKey, L"SystemStartOptions", &SystemStartOptions); 134 if (rc != ERROR_SUCCESS) 135 goto cleanup; 136 137 /* Check for CONSOLE switch in SystemStartOptions */ 138 CurrentOption = SystemStartOptions; 139 while (CurrentOption) 140 { 141 NextOption = wcschr(CurrentOption, L' '); 142 if (NextOption) 143 *NextOption = L'\0'; 144 if (wcsicmp(CurrentOption, L"CONSOLE") == 0) 145 { 146 TRACE("Found %S. Switching to console boot\n", CurrentOption); 147 ConsoleBoot = TRUE; 148 goto cleanup; 149 } 150 CurrentOption = NextOption ? NextOption + 1 : NULL; 151 } 152 153 cleanup: 154 if (ConsoleBoot) 155 pGinaUI = &GinaTextUI; 156 else 157 pGinaUI = &GinaGraphicalUI; 158 159 if (ControlKey != NULL) 160 RegCloseKey(ControlKey); 161 HeapFree(GetProcessHeap(), 0, SystemStartOptions); 162 } 163 164 165 static 166 BOOL 167 GetRegistrySettings(PGINA_CONTEXT pgContext) 168 { 169 HKEY hKey = NULL; 170 LPWSTR lpAutoAdminLogon = NULL; 171 LPWSTR lpDontDisplayLastUserName = NULL; 172 LPWSTR lpShutdownWithoutLogon = NULL; 173 LPWSTR lpIgnoreShiftOverride = NULL; 174 DWORD dwDisableCAD = 0; 175 DWORD dwSize; 176 LONG rc; 177 178 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 179 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", 180 0, 181 KEY_QUERY_VALUE, 182 &hKey); 183 if (rc != ERROR_SUCCESS) 184 { 185 WARN("RegOpenKeyExW() failed with error %lu\n", rc); 186 return FALSE; 187 } 188 189 rc = ReadRegSzValue(hKey, 190 L"AutoAdminLogon", 191 &lpAutoAdminLogon); 192 if (rc == ERROR_SUCCESS) 193 { 194 if (wcscmp(lpAutoAdminLogon, L"1") == 0) 195 pgContext->bAutoAdminLogon = TRUE; 196 } 197 198 TRACE("bAutoAdminLogon: %s\n", pgContext->bAutoAdminLogon ? "TRUE" : "FALSE"); 199 200 rc = ReadRegDwordValue(hKey, 201 L"DisableCAD", 202 &dwDisableCAD); 203 if (rc == ERROR_SUCCESS) 204 { 205 if (dwDisableCAD != 0) 206 pgContext->bDisableCAD = TRUE; 207 } 208 209 TRACE("bDisableCAD: %s\n", pgContext->bDisableCAD ? "TRUE" : "FALSE"); 210 211 pgContext->bShutdownWithoutLogon = TRUE; 212 rc = ReadRegSzValue(hKey, 213 L"ShutdownWithoutLogon", 214 &lpShutdownWithoutLogon); 215 if (rc == ERROR_SUCCESS) 216 { 217 if (wcscmp(lpShutdownWithoutLogon, L"0") == 0) 218 pgContext->bShutdownWithoutLogon = FALSE; 219 } 220 221 rc = ReadRegSzValue(hKey, 222 L"DontDisplayLastUserName", 223 &lpDontDisplayLastUserName); 224 if (rc == ERROR_SUCCESS) 225 { 226 if (wcscmp(lpDontDisplayLastUserName, L"1") == 0) 227 pgContext->bDontDisplayLastUserName = TRUE; 228 } 229 230 rc = ReadRegSzValue(hKey, 231 L"IgnoreShiftOverride", 232 &lpIgnoreShiftOverride); 233 if (rc == ERROR_SUCCESS) 234 { 235 if (wcscmp(lpIgnoreShiftOverride, L"1") == 0) 236 pgContext->bIgnoreShiftOverride = TRUE; 237 } 238 239 dwSize = sizeof(pgContext->UserName); 240 rc = RegQueryValueExW(hKey, 241 L"DefaultUserName", 242 NULL, 243 NULL, 244 (LPBYTE)&pgContext->UserName, 245 &dwSize); 246 247 dwSize = sizeof(pgContext->DomainName); 248 rc = RegQueryValueExW(hKey, 249 L"DefaultDomainName", 250 NULL, 251 NULL, 252 (LPBYTE)&pgContext->DomainName, 253 &dwSize); 254 255 dwSize = sizeof(pgContext->Password); 256 rc = RegQueryValueExW(hKey, 257 L"DefaultPassword", 258 NULL, 259 NULL, 260 (LPBYTE)&pgContext->Password, 261 &dwSize); 262 263 if (lpIgnoreShiftOverride != NULL) 264 HeapFree(GetProcessHeap(), 0, lpIgnoreShiftOverride); 265 266 if (lpShutdownWithoutLogon != NULL) 267 HeapFree(GetProcessHeap(), 0, lpShutdownWithoutLogon); 268 269 if (lpDontDisplayLastUserName != NULL) 270 HeapFree(GetProcessHeap(), 0, lpDontDisplayLastUserName); 271 272 if (lpAutoAdminLogon != NULL) 273 HeapFree(GetProcessHeap(), 0, lpAutoAdminLogon); 274 275 if (hKey != NULL) 276 RegCloseKey(hKey); 277 278 return TRUE; 279 } 280 281 typedef DWORD (WINAPI *pThemeWait)(DWORD dwTimeout); 282 typedef BOOL (WINAPI *pThemeWatch)(void); 283 284 static void 285 InitThemeSupport(VOID) 286 { 287 HMODULE hDll = LoadLibraryW(L"shsvcs.dll"); 288 pThemeWait themeWait; 289 pThemeWatch themeWatch; 290 291 if(!hDll) 292 return; 293 294 themeWait = (pThemeWait) GetProcAddress(hDll, (LPCSTR)2); 295 themeWatch = (pThemeWatch) GetProcAddress(hDll, (LPCSTR)1); 296 297 if(themeWait && themeWatch) 298 { 299 themeWait(5000); 300 themeWatch(); 301 } 302 } 303 304 /* 305 * @implemented 306 */ 307 BOOL WINAPI 308 WlxInitialize( 309 LPWSTR lpWinsta, 310 HANDLE hWlx, 311 PVOID pvReserved, 312 PVOID pWinlogonFunctions, 313 PVOID *pWlxContext) 314 { 315 PGINA_CONTEXT pgContext; 316 317 UNREFERENCED_PARAMETER(pvReserved); 318 319 InitThemeSupport(); 320 321 pgContext = (PGINA_CONTEXT)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sizeof(GINA_CONTEXT)); 322 if(!pgContext) 323 { 324 WARN("LocalAlloc() failed\n"); 325 return FALSE; 326 } 327 328 if (!GetRegistrySettings(pgContext)) 329 { 330 WARN("GetRegistrySettings() failed\n"); 331 LocalFree(pgContext); 332 return FALSE; 333 } 334 335 /* Return the context to winlogon */ 336 *pWlxContext = (PVOID)pgContext; 337 pgContext->hDllInstance = hDllInstance; 338 339 /* Save pointer to dispatch table */ 340 pgContext->pWlxFuncs = (PWLX_DISPATCH_VERSION_1_3)pWinlogonFunctions; 341 342 /* Save the winlogon handle used to call the dispatch functions */ 343 pgContext->hWlx = hWlx; 344 345 /* Save window station */ 346 pgContext->station = lpWinsta; 347 348 /* Clear status window handle */ 349 pgContext->hStatusWindow = NULL; 350 351 /* Notify winlogon that we will use the default SAS */ 352 pgContext->pWlxFuncs->WlxUseCtrlAltDel(hWlx); 353 354 /* Locates the authentication package */ 355 //LsaRegisterLogonProcess(...); 356 357 pgContext->nShutdownAction = WLX_SAS_ACTION_SHUTDOWN_POWER_OFF; 358 359 ChooseGinaUI(); 360 return pGinaUI->Initialize(pgContext); 361 } 362 363 /* 364 * @implemented 365 */ 366 BOOL 367 WINAPI 368 WlxScreenSaverNotify( 369 PVOID pWlxContext, 370 BOOL *pSecure) 371 { 372 #if 0 373 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext; 374 WCHAR szBuffer[2]; 375 HKEY hKeyCurrentUser, hKey; 376 DWORD bufferSize = sizeof(szBuffer); 377 DWORD varType = REG_SZ; 378 LONG rc; 379 380 TRACE("(%p %p)\n", pWlxContext, pSecure); 381 382 *pSecure = TRUE; 383 384 /* 385 * Policy setting: 386 * HKLM\Software\Policies\Microsoft\Windows\Control Panel\Desktop : ScreenSaverIsSecure 387 * User setting: 388 * HKCU\Control Panel\Desktop : ScreenSaverIsSecure 389 */ 390 391 if (!ImpersonateLoggedOnUser(pgContext->UserToken)) 392 { 393 ERR("WL: ImpersonateLoggedOnUser() failed with error %lu\n", GetLastError()); 394 *pSecure = FALSE; 395 return TRUE; 396 } 397 398 /* Open the current user HKCU key */ 399 rc = RegOpenCurrentUser(MAXIMUM_ALLOWED, &hKeyCurrentUser); 400 TRACE("RegOpenCurrentUser: %ld\n", rc); 401 if (rc == ERROR_SUCCESS) 402 { 403 /* Open the subkey */ 404 rc = RegOpenKeyExW(hKeyCurrentUser, 405 L"Control Panel\\Desktop", 406 0, 407 KEY_QUERY_VALUE, 408 &hKey); 409 TRACE("RegOpenKeyExW: %ld\n", rc); 410 RegCloseKey(hKeyCurrentUser); 411 } 412 413 /* Read the value */ 414 if (rc == ERROR_SUCCESS) 415 { 416 rc = RegQueryValueExW(hKey, 417 L"ScreenSaverIsSecure", 418 NULL, 419 &varType, 420 (LPBYTE)szBuffer, 421 &bufferSize); 422 423 TRACE("RegQueryValueExW: %ld\n", rc); 424 425 if (rc == ERROR_SUCCESS) 426 { 427 TRACE("szBuffer: \"%S\"\n", szBuffer); 428 *pSecure = _wtoi(szBuffer); 429 } 430 431 RegCloseKey(hKey); 432 } 433 434 /* Revert the impersonation */ 435 RevertToSelf(); 436 437 TRACE("*pSecure: %ld\n", *pSecure); 438 #endif 439 440 *pSecure = FALSE; 441 442 return TRUE; 443 } 444 445 /* 446 * @implemented 447 */ 448 BOOL WINAPI 449 WlxStartApplication( 450 PVOID pWlxContext, 451 PWSTR pszDesktopName, 452 PVOID pEnvironment, 453 PWSTR pszCmdLine) 454 { 455 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext; 456 STARTUPINFOW StartupInfo; 457 PROCESS_INFORMATION ProcessInformation; 458 WCHAR CurrentDirectory[MAX_PATH]; 459 HANDLE hAppToken; 460 UINT len; 461 BOOL ret; 462 463 len = GetWindowsDirectoryW(CurrentDirectory, MAX_PATH); 464 if (len == 0 || len > MAX_PATH) 465 { 466 ERR("GetWindowsDirectoryW() failed\n"); 467 return FALSE; 468 } 469 470 ret = DuplicateTokenEx(pgContext->UserToken, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, &hAppToken); 471 if (!ret) 472 { 473 ERR("DuplicateTokenEx() failed with error %lu\n", GetLastError()); 474 return FALSE; 475 } 476 477 ZeroMemory(&StartupInfo, sizeof(StartupInfo)); 478 ZeroMemory(&ProcessInformation, sizeof(ProcessInformation)); 479 StartupInfo.cb = sizeof(StartupInfo); 480 StartupInfo.lpTitle = pszCmdLine; 481 StartupInfo.dwFlags = STARTF_USESHOWWINDOW; 482 StartupInfo.wShowWindow = SW_SHOW; 483 StartupInfo.lpDesktop = pszDesktopName; 484 485 len = GetWindowsDirectoryW(CurrentDirectory, MAX_PATH); 486 if (len == 0 || len > MAX_PATH) 487 { 488 ERR("GetWindowsDirectoryW() failed\n"); 489 return FALSE; 490 } 491 ret = CreateProcessAsUserW( 492 hAppToken, 493 pszCmdLine, 494 NULL, 495 NULL, 496 NULL, 497 FALSE, 498 CREATE_UNICODE_ENVIRONMENT, 499 pEnvironment, 500 CurrentDirectory, 501 &StartupInfo, 502 &ProcessInformation); 503 CloseHandle(ProcessInformation.hProcess); 504 CloseHandle(ProcessInformation.hThread); 505 CloseHandle(hAppToken); 506 if (!ret) 507 ERR("CreateProcessAsUserW() failed with error %lu\n", GetLastError()); 508 return ret; 509 } 510 511 /* 512 * @implemented 513 */ 514 BOOL WINAPI 515 WlxActivateUserShell( 516 PVOID pWlxContext, 517 PWSTR pszDesktopName, 518 PWSTR pszMprLogonScript, 519 PVOID pEnvironment) 520 { 521 HKEY hKey; 522 DWORD BufSize, ValueType; 523 WCHAR pszUserInitApp[MAX_PATH + 1]; 524 WCHAR pszExpUserInitApp[MAX_PATH]; 525 DWORD len; 526 LONG rc; 527 528 TRACE("WlxActivateUserShell()\n"); 529 530 UNREFERENCED_PARAMETER(pszMprLogonScript); 531 532 /* Get the path of userinit */ 533 rc = RegOpenKeyExW( 534 HKEY_LOCAL_MACHINE, 535 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", 536 0, 537 KEY_QUERY_VALUE, 538 &hKey); 539 if (rc != ERROR_SUCCESS) 540 { 541 WARN("RegOpenKeyExW() failed with error %lu\n", rc); 542 return FALSE; 543 } 544 545 /* Query userinit application */ 546 BufSize = sizeof(pszUserInitApp) - sizeof(UNICODE_NULL); 547 rc = RegQueryValueExW( 548 hKey, 549 L"Userinit", 550 NULL, 551 &ValueType, 552 (LPBYTE)pszUserInitApp, 553 &BufSize); 554 RegCloseKey(hKey); 555 if (rc != ERROR_SUCCESS || (ValueType != REG_SZ && ValueType != REG_EXPAND_SZ)) 556 { 557 WARN("RegQueryValueExW() failed with error %lu\n", rc); 558 return FALSE; 559 } 560 pszUserInitApp[MAX_PATH] = UNICODE_NULL; 561 562 len = ExpandEnvironmentStringsW(pszUserInitApp, pszExpUserInitApp, MAX_PATH); 563 if (len > MAX_PATH) 564 { 565 WARN("ExpandEnvironmentStringsW() failed. Required size %lu\n", len); 566 return FALSE; 567 } 568 569 /* Start userinit app */ 570 return WlxStartApplication(pWlxContext, pszDesktopName, pEnvironment, pszExpUserInitApp); 571 } 572 573 /* 574 * @implemented 575 */ 576 int WINAPI 577 WlxLoggedOnSAS( 578 PVOID pWlxContext, 579 DWORD dwSasType, 580 PVOID pReserved) 581 { 582 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext; 583 INT SasAction = WLX_SAS_ACTION_NONE; 584 585 TRACE("WlxLoggedOnSAS(0x%lx)\n", dwSasType); 586 587 UNREFERENCED_PARAMETER(pReserved); 588 589 switch (dwSasType) 590 { 591 case WLX_SAS_TYPE_CTRL_ALT_DEL: 592 case WLX_SAS_TYPE_TIMEOUT: 593 { 594 SasAction = pGinaUI->LoggedOnSAS(pgContext, dwSasType); 595 break; 596 } 597 case WLX_SAS_TYPE_SC_INSERT: 598 { 599 FIXME("WlxLoggedOnSAS: SasType WLX_SAS_TYPE_SC_INSERT not supported!\n"); 600 break; 601 } 602 case WLX_SAS_TYPE_SC_REMOVE: 603 { 604 FIXME("WlxLoggedOnSAS: SasType WLX_SAS_TYPE_SC_REMOVE not supported!\n"); 605 break; 606 } 607 default: 608 { 609 WARN("WlxLoggedOnSAS: Unknown SasType: 0x%x\n", dwSasType); 610 break; 611 } 612 } 613 614 return SasAction; 615 } 616 617 /* 618 * @implemented 619 */ 620 BOOL WINAPI 621 WlxDisplayStatusMessage( 622 IN PVOID pWlxContext, 623 IN HDESK hDesktop, 624 IN DWORD dwOptions, 625 IN PWSTR pTitle, 626 IN PWSTR pMessage) 627 { 628 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext; 629 630 TRACE("WlxDisplayStatusMessage(\"%S\")\n", pMessage); 631 632 return pGinaUI->DisplayStatusMessage(pgContext, hDesktop, dwOptions, pTitle, pMessage); 633 } 634 635 /* 636 * @implemented 637 */ 638 BOOL WINAPI 639 WlxRemoveStatusMessage( 640 IN PVOID pWlxContext) 641 { 642 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext; 643 644 TRACE("WlxRemoveStatusMessage()\n"); 645 646 return pGinaUI->RemoveStatusMessage(pgContext); 647 } 648 649 static PWSTR 650 DuplicationString(PWSTR Str) 651 { 652 DWORD cb; 653 PWSTR NewStr; 654 655 if (Str == NULL) return NULL; 656 657 cb = (wcslen(Str) + 1) * sizeof(WCHAR); 658 if ((NewStr = LocalAlloc(LMEM_FIXED, cb))) 659 memcpy(NewStr, Str, cb); 660 return NewStr; 661 } 662 663 664 BOOL 665 DoAdminUnlock( 666 IN PGINA_CONTEXT pgContext, 667 IN PWSTR UserName, 668 IN PWSTR Domain, 669 IN PWSTR Password) 670 { 671 HANDLE hToken = NULL; 672 PTOKEN_GROUPS Groups = NULL; 673 BOOL bIsAdmin = FALSE; 674 ULONG Size; 675 ULONG i; 676 NTSTATUS Status; 677 NTSTATUS SubStatus = STATUS_SUCCESS; 678 679 TRACE("(%S %S %S)\n", UserName, Domain, Password); 680 681 Status = ConnectToLsa(pgContext); 682 if (!NT_SUCCESS(Status)) 683 { 684 WARN("ConnectToLsa() failed\n"); 685 return FALSE; 686 } 687 688 Status = MyLogonUser(pgContext->LsaHandle, 689 pgContext->AuthenticationPackage, 690 UserName, 691 Domain, 692 Password, 693 &pgContext->UserToken, 694 &SubStatus); 695 if (!NT_SUCCESS(Status)) 696 { 697 WARN("MyLogonUser() failed\n"); 698 return FALSE; 699 } 700 701 Status = NtQueryInformationToken(hToken, 702 TokenGroups, 703 NULL, 704 0, 705 &Size); 706 if ((Status != STATUS_SUCCESS) && (Status != STATUS_BUFFER_TOO_SMALL)) 707 { 708 TRACE("NtQueryInformationToken() failed (Status 0x%08lx)\n", Status); 709 goto done; 710 } 711 712 Groups = HeapAlloc(GetProcessHeap(), 0, Size); 713 if (Groups == NULL) 714 { 715 TRACE("HeapAlloc() failed\n"); 716 goto done; 717 } 718 719 Status = NtQueryInformationToken(hToken, 720 TokenGroups, 721 Groups, 722 Size, 723 &Size); 724 if (!NT_SUCCESS(Status)) 725 { 726 TRACE("NtQueryInformationToken() failed (Status 0x%08lx)\n", Status); 727 goto done; 728 } 729 730 for (i = 0; i < Groups->GroupCount; i++) 731 { 732 if (RtlEqualSid(Groups->Groups[i].Sid, AdminSid)) 733 { 734 TRACE("Member of Admins group\n"); 735 bIsAdmin = TRUE; 736 break; 737 } 738 } 739 740 done: 741 if (Groups != NULL) 742 HeapFree(GetProcessHeap(), 0, Groups); 743 744 if (hToken != NULL) 745 CloseHandle(hToken); 746 747 return bIsAdmin; 748 } 749 750 751 NTSTATUS 752 DoLoginTasks( 753 IN OUT PGINA_CONTEXT pgContext, 754 IN PWSTR UserName, 755 IN PWSTR Domain, 756 IN PWSTR Password, 757 OUT PNTSTATUS SubStatus) 758 { 759 NTSTATUS Status; 760 761 Status = ConnectToLsa(pgContext); 762 if (!NT_SUCCESS(Status)) 763 { 764 WARN("ConnectToLsa() failed (Status 0x%08lx)\n", Status); 765 return Status; 766 } 767 768 Status = MyLogonUser(pgContext->LsaHandle, 769 pgContext->AuthenticationPackage, 770 UserName, 771 Domain, 772 Password, 773 &pgContext->UserToken, 774 SubStatus); 775 if (!NT_SUCCESS(Status)) 776 { 777 WARN("MyLogonUser() failed (Status 0x%08lx)\n", Status); 778 } 779 780 return Status; 781 } 782 783 784 BOOL 785 CreateProfile( 786 IN OUT PGINA_CONTEXT pgContext, 787 IN PWSTR UserName, 788 IN PWSTR Domain, 789 IN PWSTR Password) 790 { 791 LPWSTR ProfilePath = NULL; 792 LPWSTR lpEnvironment = NULL; 793 TOKEN_STATISTICS Stats; 794 PWLX_PROFILE_V2_0 pProfile = NULL; 795 DWORD cbStats, cbSize; 796 DWORD dwLength; 797 BOOL bResult; 798 799 /* Store the logon time in the context */ 800 GetLocalTime(&pgContext->LogonTime); 801 802 /* Store user and domain in the context */ 803 wcscpy(pgContext->UserName, UserName); 804 if (Domain == NULL || wcslen(Domain) == 0) 805 { 806 dwLength = _countof(pgContext->DomainName); 807 GetComputerNameW(pgContext->DomainName, &dwLength); 808 } 809 else 810 { 811 wcscpy(pgContext->DomainName, Domain); 812 } 813 814 /* Get profile path */ 815 cbSize = 0; 816 bResult = GetProfilesDirectoryW(NULL, &cbSize); 817 if (!bResult && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 818 { 819 ProfilePath = HeapAlloc(GetProcessHeap(), 0, cbSize * sizeof(WCHAR)); 820 if (!ProfilePath) 821 { 822 WARN("HeapAlloc() failed\n"); 823 goto cleanup; 824 } 825 bResult = GetProfilesDirectoryW(ProfilePath, &cbSize); 826 } 827 if (!bResult) 828 { 829 WARN("GetUserProfileDirectoryW() failed\n"); 830 goto cleanup; 831 } 832 833 /* Allocate memory for profile */ 834 pProfile = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WLX_PROFILE_V2_0)); 835 if (!pProfile) 836 { 837 WARN("HeapAlloc() failed\n"); 838 goto cleanup; 839 } 840 pProfile->dwType = WLX_PROFILE_TYPE_V2_0; 841 pProfile->pszProfile = ProfilePath; 842 843 cbSize = sizeof(L"LOGONSERVER=\\\\") + 844 wcslen(pgContext->DomainName) * sizeof(WCHAR) + 845 sizeof(UNICODE_NULL); 846 lpEnvironment = HeapAlloc(GetProcessHeap(), 0, cbSize); 847 if (!lpEnvironment) 848 { 849 WARN("HeapAlloc() failed\n"); 850 goto cleanup; 851 } 852 853 StringCbPrintfW(lpEnvironment, cbSize, L"LOGONSERVER=\\\\%ls", pgContext->DomainName); 854 ASSERT(wcslen(lpEnvironment) == cbSize / sizeof(WCHAR) - 2); 855 lpEnvironment[cbSize / sizeof(WCHAR) - 1] = UNICODE_NULL; 856 857 pProfile->pszEnvironment = lpEnvironment; 858 859 if (!GetTokenInformation(pgContext->UserToken, 860 TokenStatistics, 861 &Stats, 862 sizeof(Stats), 863 &cbStats)) 864 { 865 WARN("Couldn't get Authentication id from user token!\n"); 866 goto cleanup; 867 } 868 869 *pgContext->pAuthenticationId = Stats.AuthenticationId; 870 pgContext->pMprNotifyInfo->pszUserName = DuplicationString(UserName); 871 pgContext->pMprNotifyInfo->pszDomain = DuplicationString(Domain); 872 pgContext->pMprNotifyInfo->pszPassword = DuplicationString(Password); 873 pgContext->pMprNotifyInfo->pszOldPassword = NULL; 874 *pgContext->pdwOptions = 0; 875 *pgContext->pProfile = pProfile; 876 return TRUE; 877 878 cleanup: 879 if (pProfile) 880 { 881 HeapFree(GetProcessHeap(), 0, pProfile->pszEnvironment); 882 } 883 HeapFree(GetProcessHeap(), 0, pProfile); 884 HeapFree(GetProcessHeap(), 0, ProfilePath); 885 return FALSE; 886 } 887 888 889 /* 890 * @implemented 891 */ 892 VOID WINAPI 893 WlxDisplaySASNotice( 894 IN PVOID pWlxContext) 895 { 896 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext; 897 898 TRACE("WlxDisplaySASNotice(%p)\n", pWlxContext); 899 900 if (GetSystemMetrics(SM_REMOTESESSION)) 901 { 902 /* User is remotely logged on. Don't display a notice */ 903 pgContext->pWlxFuncs->WlxSasNotify(pgContext->hWlx, WLX_SAS_TYPE_CTRL_ALT_DEL); 904 return; 905 } 906 907 if (pgContext->bAutoAdminLogon) 908 { 909 if (pgContext->bIgnoreShiftOverride || 910 (GetKeyState(VK_SHIFT) >= 0)) 911 { 912 /* Don't display the window, we want to do an automatic logon */ 913 pgContext->pWlxFuncs->WlxSasNotify(pgContext->hWlx, WLX_SAS_TYPE_CTRL_ALT_DEL); 914 return; 915 } 916 917 pgContext->bAutoAdminLogon = FALSE; 918 } 919 920 if (pgContext->bDisableCAD) 921 { 922 pgContext->pWlxFuncs->WlxSasNotify(pgContext->hWlx, WLX_SAS_TYPE_CTRL_ALT_DEL); 923 return; 924 } 925 926 pGinaUI->DisplaySASNotice(pgContext); 927 928 TRACE("WlxDisplaySASNotice() done\n"); 929 } 930 931 /* 932 * @implemented 933 */ 934 INT WINAPI 935 WlxLoggedOutSAS( 936 IN PVOID pWlxContext, 937 IN DWORD dwSasType, 938 OUT PLUID pAuthenticationId, 939 IN OUT PSID pLogonSid, 940 OUT PDWORD pdwOptions, 941 OUT PHANDLE phToken, 942 OUT PWLX_MPR_NOTIFY_INFO pMprNotifyInfo, 943 OUT PVOID *pProfile) 944 { 945 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext; 946 INT res; 947 948 TRACE("WlxLoggedOutSAS()\n"); 949 950 UNREFERENCED_PARAMETER(dwSasType); 951 UNREFERENCED_PARAMETER(pLogonSid); 952 953 pgContext->pAuthenticationId = pAuthenticationId; 954 pgContext->pdwOptions = pdwOptions; 955 pgContext->pMprNotifyInfo = pMprNotifyInfo; 956 pgContext->pProfile = pProfile; 957 958 959 res = pGinaUI->LoggedOutSAS(pgContext); 960 *phToken = pgContext->UserToken; 961 return res; 962 } 963 964 /* 965 * @implemented 966 */ 967 int WINAPI 968 WlxWkstaLockedSAS( 969 PVOID pWlxContext, 970 DWORD dwSasType) 971 { 972 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext; 973 974 TRACE("WlxWkstaLockedSAS()\n"); 975 976 UNREFERENCED_PARAMETER(dwSasType); 977 978 return pGinaUI->LockedSAS(pgContext); 979 } 980 981 982 /* 983 * @implemented 984 */ 985 VOID 986 WINAPI 987 WlxDisplayLockedNotice(PVOID pWlxContext) 988 { 989 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext; 990 991 TRACE("WlxDisplayLockedNotice()\n"); 992 993 if (pgContext->bDisableCAD) 994 { 995 pgContext->pWlxFuncs->WlxSasNotify(pgContext->hWlx, WLX_SAS_TYPE_CTRL_ALT_DEL); 996 return; 997 } 998 999 pGinaUI->DisplayLockedNotice(pgContext); 1000 } 1001 1002 1003 /* 1004 * @implemented 1005 */ 1006 BOOL WINAPI 1007 WlxIsLogoffOk( 1008 PVOID pWlxContext) 1009 { 1010 TRACE("WlxIsLogoffOk()\n"); 1011 UNREFERENCED_PARAMETER(pWlxContext); 1012 return TRUE; 1013 } 1014 1015 1016 /* 1017 * @implemented 1018 */ 1019 VOID WINAPI 1020 WlxLogoff( 1021 PVOID pWlxContext) 1022 { 1023 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext; 1024 1025 TRACE("WlxLogoff(%p)\n", pWlxContext); 1026 1027 /* Delete the password */ 1028 ZeroMemory(pgContext->Password, sizeof(pgContext->Password)); 1029 1030 /* Close the user token */ 1031 CloseHandle(pgContext->UserToken); 1032 pgContext->UserToken = NULL; 1033 } 1034 1035 1036 /* 1037 * @implemented 1038 */ 1039 VOID WINAPI 1040 WlxShutdown( 1041 PVOID pWlxContext, 1042 DWORD ShutdownType) 1043 { 1044 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext; 1045 NTSTATUS Status; 1046 1047 TRACE("WlxShutdown(%p %lx)\n", pWlxContext, ShutdownType); 1048 1049 /* Close the LSA handle */ 1050 pgContext->AuthenticationPackage = 0; 1051 Status = LsaDeregisterLogonProcess(pgContext->LsaHandle); 1052 if (!NT_SUCCESS(Status)) 1053 { 1054 ERR("LsaDeregisterLogonProcess failed (Status 0x%08lx)\n", Status); 1055 } 1056 } 1057 1058 1059 BOOL WINAPI 1060 DllMain( 1061 IN HINSTANCE hinstDLL, 1062 IN DWORD dwReason, 1063 IN LPVOID lpvReserved) 1064 { 1065 UNREFERENCED_PARAMETER(lpvReserved); 1066 1067 if (dwReason == DLL_PROCESS_ATTACH) 1068 { 1069 hDllInstance = hinstDLL; 1070 1071 RtlAllocateAndInitializeSid(&SystemAuthority, 1072 2, 1073 SECURITY_BUILTIN_DOMAIN_RID, 1074 DOMAIN_ALIAS_RID_ADMINS, 1075 SECURITY_NULL_RID, 1076 SECURITY_NULL_RID, 1077 SECURITY_NULL_RID, 1078 SECURITY_NULL_RID, 1079 SECURITY_NULL_RID, 1080 SECURITY_NULL_RID, 1081 &AdminSid); 1082 1083 } 1084 else if (dwReason == DLL_PROCESS_DETACH) 1085 { 1086 if (AdminSid != NULL) 1087 RtlFreeSid(AdminSid); 1088 } 1089 1090 return TRUE; 1091 } 1092