|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: shell.c
//
// Contents: Microsoft Logon GUI DLL
//
// History: 7-14-94 RichardW Created
//
//----------------------------------------------------------------------------
#include "msgina.h"
#include "shtdnp.h"
#include <stdio.h>
#include <wchar.h>
#include <regapi.h>
#include <ginacomn.h>
HICON hNoDCIcon;
#if DBG
DWORD DebugAllowNoShell = 1; #else
DWORD DebugAllowNoShell = 0; #endif
//
// Parsing information for autoexec.bat
//
#define PARSE_AUTOEXEC_KEY TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon")
#define PARSE_AUTOEXEC_ENTRY TEXT("ParseAutoexec")
#define PARSE_AUTOEXEC_DEFAULT TEXT("1")
#define MAX_PARSE_AUTOEXEC_BUFFER 2
BOOL SetLogonScriptVariables( PGLOBALS pGlobals, PVOID * pEnvironment );
BOOL SetAutoEnrollVariables( PGLOBALS pGlobals, PVOID * pEnvironment );
VOID DeleteLogonScriptVariables( PGLOBALS pGlobals, PVOID * pEnvironment );
void CtxCreateMigrateEnv( PVOID ); void CtxDeleteMigrateEnv( VOID );
BOOL DoAutoexecStuff( PGLOBALS pGlobals, PVOID * ppEnvironment, LPTSTR pszPathVar) { HKEY hKey; DWORD dwDisp, dwType, dwMaxBufferSize; //
// Set the default case
//
TCHAR szParseAutoexec[MAX_PARSE_AUTOEXEC_BUFFER] = PARSE_AUTOEXEC_DEFAULT;
//
// Impersonate the user, and check the registry
//
if (OpenHKeyCurrentUser(pGlobals)) {
if (RegCreateKeyEx (pGlobals->UserProcessData.hCurrentUser, PARSE_AUTOEXEC_KEY, 0, 0, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hKey, &dwDisp) == ERROR_SUCCESS) {
//
// Query the current value. If it doesn't exist, then add
// the entry for next time.
//
dwMaxBufferSize = sizeof (TCHAR) * MAX_PARSE_AUTOEXEC_BUFFER; if (RegQueryValueEx (hKey, PARSE_AUTOEXEC_ENTRY, NULL, &dwType, (LPBYTE) szParseAutoexec, &dwMaxBufferSize) != ERROR_SUCCESS) {
//
// Set the default value
//
RegSetValueEx (hKey, PARSE_AUTOEXEC_ENTRY, 0, REG_SZ, (LPBYTE) szParseAutoexec, sizeof (TCHAR) * (lstrlen (szParseAutoexec) + 1)); }
//
// Close key
//
RegCloseKey (hKey); }
//
// Close HKCU
//
CloseHKeyCurrentUser(pGlobals);
}
//
// Process the autoexec if appropriate
//
if (szParseAutoexec[0] == TEXT('1')) { ProcessAutoexec(ppEnvironment, PATH_VARIABLE); }
return(TRUE); }
//+---------------------------------------------------------------------------
//
// Function: UpdateUserEnvironment
//
// Synopsis:
//
// Arguments: [pGlobals] --
// [ppEnvironment] --
//
// History: 11-01-94 RichardW Created
//
// Notes:
//
//----------------------------------------------------------------------------
VOID UpdateUserEnvironment( PGLOBALS pGlobals, PVOID * ppEnvironment, PWSTR pszOldDir ) { BOOL DeepShare; TCHAR lpHomeShare[MAX_PATH] = TEXT(""); TCHAR lpHomePath[MAX_PATH] = TEXT(""); TCHAR lpHomeDrive[4] = TEXT(""); TCHAR lpHomeDirectory[MAX_PATH] = TEXT(""); BOOL TSHomeDir = FALSE; TCHAR lpSmartcard[sizeof(pGlobals->Smartcard) + 1 + sizeof(pGlobals->SmartcardReader) + 1];
/*
* Initialize user's environment. */
SetUserEnvironmentVariable(ppEnvironment, USERNAME_VARIABLE, (LPTSTR)pGlobals->FlatUserName.Buffer, TRUE); SetUserEnvironmentVariable(ppEnvironment, USERDOMAIN_VARIABLE, (LPTSTR)pGlobals->FlatDomain.Buffer, TRUE);
if (pGlobals->Smartcard[0] && pGlobals->SmartcardReader[0]) {
_snwprintf( lpSmartcard, sizeof(lpSmartcard) / sizeof(TCHAR), TEXT("%s;%s"), pGlobals->Smartcard, pGlobals->SmartcardReader ); // Will always be 0 terminated given the size of lpSmartcard
SetUserEnvironmentVariable(ppEnvironment, SMARTCARD_VARIABLE, lpSmartcard, TRUE); }
if ( !g_Console ) { // See if the user specified a TerminalServer Home Directory.
// If so, we override the regular directory
if (lstrlen(pGlobals->MuGlobals.TSData.HomeDir) > 0) { ASSERT (sizeof(lpHomeDirectory) >= sizeof(pGlobals->MuGlobals.TSData.HomeDir)); lstrcpy(lpHomeDirectory, pGlobals->MuGlobals.TSData.HomeDir); TSHomeDir = TRUE; } if (lstrlen(pGlobals->MuGlobals.TSData.HomeDirDrive) > 0) { ASSERT(sizeof(lpHomeDrive) >= sizeof(pGlobals->MuGlobals.TSData.HomeDirDrive)); lstrcpy(lpHomeDrive, pGlobals->MuGlobals.TSData.HomeDirDrive); TSHomeDir = TRUE; } }
if (!TSHomeDir && pGlobals->Profile) { if (pGlobals->Profile->HomeDirectoryDrive.Length && (pGlobals->Profile->HomeDirectoryDrive.Length + sizeof(WCHAR)) <= sizeof(lpHomeDrive)) { memcpy(lpHomeDrive, pGlobals->Profile->HomeDirectoryDrive.Buffer, pGlobals->Profile->HomeDirectoryDrive.Length); lpHomeDrive[pGlobals->Profile->HomeDirectoryDrive.Length / sizeof(WCHAR)] = 0; }
if (pGlobals->Profile->HomeDirectory.Length && (pGlobals->Profile->HomeDirectory.Length + sizeof(WCHAR)) <= (MAX_PATH*sizeof(TCHAR))) { memcpy(lpHomeDirectory, pGlobals->Profile->HomeDirectory.Buffer, pGlobals->Profile->HomeDirectory.Length); lpHomeDirectory[pGlobals->Profile->HomeDirectory.Length / sizeof(WCHAR)] = 0; } }
SetHomeDirectoryEnvVars(ppEnvironment, lpHomeDirectory, lpHomeDrive, lpHomeShare, lpHomePath, &DeepShare);
ChangeToHomeDirectory( pGlobals, ppEnvironment, lpHomeDirectory, lpHomeDrive, lpHomeShare, lpHomePath, pszOldDir, DeepShare );
DoAutoexecStuff(pGlobals, ppEnvironment, PATH_VARIABLE);
SetEnvironmentVariables(pGlobals, USER_ENV_SUBKEY, ppEnvironment); SetEnvironmentVariables(pGlobals, USER_VOLATILE_ENV_SUBKEY, ppEnvironment);
AppendNTPathWithAutoexecPath(ppEnvironment, PATH_VARIABLE, AUTOEXECPATH_VARIABLE);
if (!g_Console) { HKEY Handle; DWORD fPerSessionTempDir = 0; DWORD dwValueData;
/*
* Open registry value set thru TSCC */ if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0, KEY_READ, &Handle ) == ERROR_SUCCESS ) { DWORD ValueSize; DWORD ValueType; LONG rc;
ValueSize = sizeof(fPerSessionTempDir);
/*
* Read registry value */ rc = RegQueryValueExW( Handle, REG_TERMSRV_PERSESSIONTEMPDIR, NULL, &ValueType, (LPBYTE) &fPerSessionTempDir, &ValueSize );
/*
* Close registry and key handle */ RegCloseKey( Handle ); }
/*
* Check the machine wide policy set thru Group Policy */
if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, TS_POLICY_SUB_TREE, 0, KEY_READ, &Handle ) == ERROR_SUCCESS ) { DWORD ValueSize; DWORD ValueType; LONG rc;
ValueSize = sizeof(dwValueData);
/*
* Read registry value */ rc = RegQueryValueExW( Handle, REG_TERMSRV_PERSESSIONTEMPDIR, NULL, &ValueType, (LPBYTE) &dwValueData, &ValueSize );
if (rc == ERROR_SUCCESS ) { fPerSessionTempDir = dwValueData; }
/*
* Close registry and key handle */ RegCloseKey( Handle ); }
if (fPerSessionTempDir) { PTERMSRVCREATETEMPDIR pfnTermsrvCreateTempDir; HANDLE dllHandle;
dllHandle = LoadLibrary(TEXT("wlnotify.dll")); if (dllHandle) { pfnTermsrvCreateTempDir = (PTERMSRVCREATETEMPDIR) GetProcAddress( dllHandle, "TermsrvCreateTempDir" ); if (pfnTermsrvCreateTempDir) { pfnTermsrvCreateTempDir( ppEnvironment, pGlobals->UserProcessData.UserToken, pGlobals->UserProcessData.NewThreadTokenSD); }
FreeLibrary(dllHandle); } } } }
BOOL ExecApplication( IN LPTSTR pch, IN LPTSTR Desktop, IN PGLOBALS pGlobals, IN PVOID pEnvironment, IN DWORD Flags, IN DWORD StartupFlags, IN BOOL RestrictProcess, OUT PPROCESS_INFORMATION ProcessInformation ) { STARTUPINFO si; BOOL Result, IgnoreResult; HANDLE ImpersonationHandle; HANDLE ProcessToken;
//
// Initialize process startup info
//
si.cb = sizeof(STARTUPINFO); si.lpReserved = pch; si.lpTitle = pch; si.dwX = si.dwY = si.dwXSize = si.dwYSize = 0L; si.dwFlags = StartupFlags; si.wShowWindow = SW_SHOW; // at least let the guy see it
si.lpReserved2 = NULL; si.cbReserved2 = 0; si.lpDesktop = Desktop;
//
// Impersonate the user so we get access checked correctly on
// the file we're trying to execute
//
ImpersonationHandle = ImpersonateUser(&pGlobals->UserProcessData, NULL); if (ImpersonationHandle == NULL) { WLPrint(("ExecApplication failed to impersonate user")); return(FALSE); }
if (RestrictProcess && (pGlobals->UserProcessData.RestrictedToken != NULL) ) { ProcessToken = pGlobals->UserProcessData.RestrictedToken; } else { ProcessToken = pGlobals->UserProcessData.UserToken; }
//
// Create the app suspended
//
DebugLog((DEB_TRACE, "About to create process of %ws, on desktop %ws\n", pch, Desktop)); Result = CreateProcessAsUser( ProcessToken, NULL, pch, NULL, NULL, FALSE, Flags | CREATE_SUSPENDED | CREATE_UNICODE_ENVIRONMENT, pEnvironment, NULL, &si, ProcessInformation);
IgnoreResult = StopImpersonating(ImpersonationHandle); ASSERT(IgnoreResult);
return(Result);
}
BOOL SetProcessQuotas( PGLOBALS pGlobals, PPROCESS_INFORMATION ProcessInformation, PUSER_PROCESS_DATA UserProcessData ) { NTSTATUS Status = STATUS_SUCCESS; BOOL Result; QUOTA_LIMITS RequestedLimits; UINT MessageId ;
RequestedLimits = UserProcessData->Quotas; RequestedLimits.MinimumWorkingSetSize = 0; RequestedLimits.MaximumWorkingSetSize = 0;
if (UserProcessData->Quotas.PagedPoolLimit != 0) {
Result = EnablePrivilege(SE_INCREASE_QUOTA_PRIVILEGE, TRUE); if (!Result) { WLPrint(("failed to enable increase_quota privilege")); return(FALSE); }
Status = NtSetInformationProcess( ProcessInformation->hProcess, ProcessQuotaLimits, (PVOID)&RequestedLimits, (ULONG)sizeof(QUOTA_LIMITS) );
Result = EnablePrivilege(SE_INCREASE_QUOTA_PRIVILEGE, FALSE); if (!Result) { WLPrint(("failed to disable increase_quota privilege")); } }
if (STATUS_QUOTA_EXCEEDED == Status) {
if ( TestTokenForAdmin( UserProcessData->UserToken ) ) { MessageId = IDS_QUOTAEXHAUSTED ; Status = STATUS_SUCCESS ; } else { MessageId = IDS_COULDNTSETQUOTAS ; } // Display a warning in this case
TimeoutMessageBox(pGlobals->hwndLogon, pGlobals, MessageId, IDS_LOGON_MESSAGE, MB_OK | MB_ICONERROR, TIMEOUT_NONE); }
#if DBG
if (!NT_SUCCESS(Status)) { WLPrint(("SetProcessQuotas failed. Status: 0x%lx", Status)); } #endif //DBG
return (NT_SUCCESS(Status)); }
DWORD ExecProcesses( PVOID pWlxContext, IN LPTSTR Desktop, IN PWSTR Processes, PVOID *ppEnvironment, DWORD Flags, DWORD StartupFlags ) { PWCH pchData; PROCESS_INFORMATION ProcessInformation; DWORD dwExecuted = 0 ; PWSTR pszTok; PGLOBALS pGlobals = (PGLOBALS) pWlxContext; WCHAR szCurrentDir[MAX_PATH];
pchData = Processes;
szCurrentDir[0] = L'\0';
if (*ppEnvironment) { UpdateUserEnvironment(pGlobals, ppEnvironment, szCurrentDir); }
SetLogonScriptVariables(pGlobals, ppEnvironment);
//we should not lauch autoenrollment in this case as it blocks the shell
//SetAutoEnrollVariables( pGlobals, ppEnvironment );
if (g_IsTerminalServer) { CtxCreateMigrateEnv( *ppEnvironment ); pWlxFuncs->WlxWin31Migrate(pGlobals->hGlobalWlx); CtxDeleteMigrateEnv( ); }
pszTok = wcstok(pchData, TEXT(",")); while (pszTok) { if (*pszTok == TEXT(' ')) { while (*pszTok++ == TEXT(' ')) ; } if (ExecApplication((LPTSTR)pszTok, Desktop, pGlobals, *ppEnvironment, Flags, StartupFlags, TRUE, // restrict application
&ProcessInformation)) { dwExecuted++;
if (SetProcessQuotas(pGlobals, &ProcessInformation, &pGlobals->UserProcessData)) { ResumeThread(ProcessInformation.hThread); } else { // OK as the process was created suspended
TerminateProcess(ProcessInformation.hProcess, ERROR_ACCESS_DENIED); }
CloseHandle(ProcessInformation.hThread); CloseHandle(ProcessInformation.hProcess);
} else {
DebugLog((DEB_WARN, "Cannot start %ws on %ws, error %d.", pszTok, Desktop, GetLastError())); }
pszTok = wcstok(NULL, TEXT(","));
}
DeleteLogonScriptVariables(pGlobals, ppEnvironment);
if ( szCurrentDir[0] ) { SetCurrentDirectory(szCurrentDir); }
return dwExecuted ; }
INT_PTR NoDCDlgProc( HWND hDlg, UINT Message, WPARAM wParam, LPARAM lParam ) { DWORD Button; HWND hwnd;
switch (Message) { case WM_INITDIALOG: CentreWindow( hDlg ); if ( !hNoDCIcon ) { hNoDCIcon = LoadImage( hDllInstance, MAKEINTRESOURCE( IDI_NODC_ICON ), IMAGE_ICON, 64, 64, LR_DEFAULTCOLOR ); } SendMessage( GetDlgItem( hDlg, IDD_NODC_FRAME ), STM_SETICON, (WPARAM) hNoDCIcon, 0 );
if ( GetProfileInt( WINLOGON, TEXT("AllowDisableDCNotify"), 0 ) ) { hwnd = GetDlgItem( hDlg, IDD_NODC_TEXT2 ); ShowWindow( hwnd, SW_HIDE ); EnableWindow( hwnd, FALSE ); } else { hwnd = GetDlgItem( hDlg, IDD_NODC_CHECK ); CheckDlgButton( hDlg, IDD_NODC_CHECK, BST_UNCHECKED ); ShowWindow( hwnd, SW_HIDE ); EnableWindow( hwnd, FALSE );
}
return( TRUE );
case WM_COMMAND: if (LOWORD(wParam) == IDOK) { Button = IsDlgButtonChecked( hDlg, IDD_NODC_CHECK ); EndDialog( hDlg, Button ); return( TRUE ); }
}
return( FALSE ); }
VOID DoNoDCDialog( PGLOBALS pGlobals ) { HKEY hKey; int err; DWORD disp; DWORD Flag; DWORD dwType; DWORD cbData; BOOL MappedHKey; PWSTR ReportControllerMissing;
Flag = 1; hKey = NULL ;
if (OpenHKeyCurrentUser(pGlobals)) { MappedHKey = TRUE;
err = RegCreateKeyEx( pGlobals->UserProcessData.hCurrentUser, WINLOGON_USER_KEY, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hKey, &disp ); if (err == 0) { cbData = sizeof(DWORD);
err = RegQueryValueEx( hKey, NODCMESSAGE, NULL, &dwType, (LPBYTE) &Flag, &cbData );
if (err != ERROR_SUCCESS || dwType != REG_DWORD) { Flag = 1; }
} else { hKey = NULL; }
} else { MappedHKey = FALSE; }
if ( Flag ) { ReportControllerMissing = AllocAndGetProfileString( APPLICATION_NAME, REPORT_CONTROLLER_MISSING, TEXT("FALSE") );
if ( ReportControllerMissing ) { if ( lstrcmp( ReportControllerMissing, TEXT("TRUE")) == 0 ) { Flag = 1; } else { Flag = 0; }
Free( ReportControllerMissing ); } else { Flag = 1; }
}
if (Flag) { pWlxFuncs->WlxSetTimeout( pGlobals->hGlobalWlx, 120 );
Flag = pWlxFuncs->WlxDialogBoxParam( pGlobals->hGlobalWlx, hDllInstance, (LPTSTR) IDD_NODC_DIALOG, NULL, NoDCDlgProc, 0 ); } else { Flag = BST_CHECKED; }
if (hKey) { if (Flag == BST_CHECKED) { Flag = 0; } else { Flag = 1; }
RegSetValueEx( hKey, NODCMESSAGE, 0, REG_DWORD, (LPBYTE) &Flag, sizeof(DWORD) );
RegCloseKey( hKey );
}
if (MappedHKey) { CloseHKeyCurrentUser(pGlobals); } }
//+---------------------------------------------------------------------------
//
// Function: GetPasswordExpiryWarningPeriod
//
// Synopsis: Returns the password expiry warning period in days: either
// the value in the registry or the default value.
//
// Arguments: None
//
// Returns: Password expiry warning period in days.
//
// History: 10-09-01 CenkE Copied from ShouldPasswordExpiryWarningBeShown
//
//----------------------------------------------------------------------------
DWORD GetPasswordExpiryWarningPeriod ( VOID ) { HKEY hKey; DWORD dwSize; DWORD dwType; DWORD DaysToCheck;
DaysToCheck = PASSWORD_EXPIRY_WARNING_DAYS;
if (RegOpenKey(HKEY_LOCAL_MACHINE, WINLOGON_USER_KEY, &hKey) == 0) { dwSize = sizeof(DWORD);
if (RegQueryValueEx(hKey, PASSWORD_EXPIRY_WARNING, 0, &dwType, (LPBYTE) &DaysToCheck, &dwSize ) || (dwType != REG_DWORD) ) { DaysToCheck = PASSWORD_EXPIRY_WARNING_DAYS; }
RegCloseKey(hKey); } return DaysToCheck; }
//+---------------------------------------------------------------------------
//
// Function: GetDaysToExpiry
//
// Synopsis: If the passed in times can be converted to seconds since 1980,
// returns how many days there are from CurrentTime to ExpiryTime
//
// Arguments: CurrentTime -- This can be the current time or the time of a
// logon etc. as FILETIME.
// ExpiryTime -- PasswordMustChange time from profile.
// DaysToExpiry -- If successful, days to password expiry is
// returned here.
//
// Returns: TRUE - DaysToExpiry could be calculated.
// FALSE - DaysToExpiry could not be calculated, or the password
// never expires.
//
// History: 10-09-01 CenkE Copied from ShouldPasswordExpiryWarningBeShown
//
//----------------------------------------------------------------------------
#define SECONDS_PER_DAY (60*60*24)
BOOL GetDaysToExpiry ( IN PLARGE_INTEGER CurrentTime, IN PLARGE_INTEGER ExpiryTime, OUT PDWORD DaysToExpiry ) { ULONG ElapsedSecondsNow; ULONG ElapsedSecondsPasswordExpires;
//
// Convert the expiry time to seconds.
//
if (!RtlTimeToSecondsSince1980(ExpiryTime, &ElapsedSecondsPasswordExpires)) { //
// The time was not expressable in 32-bit seconds
// Set seconds to password expiry based on whether the expiry
// time is way in the past or way in the future.
//
// Never expires?
if (ExpiryTime->QuadPart > CurrentTime->QuadPart) { return FALSE; }
ElapsedSecondsPasswordExpires = 0; // Already expired
}
//
// Convert the start time to seconds.
//
if (!RtlTimeToSecondsSince1980(CurrentTime, &ElapsedSecondsNow)) { return FALSE; }
if (ElapsedSecondsPasswordExpires < ElapsedSecondsNow) { (*DaysToExpiry) = 0; } else { (*DaysToExpiry) = (ElapsedSecondsPasswordExpires - ElapsedSecondsNow)/SECONDS_PER_DAY; }
return TRUE; } BOOL ShouldPasswordExpiryWarningBeShown( IN PGLOBALS pGlobals, IN BOOL LogonCheck, OUT PDWORD pDaysToExpiry ) { ULONG DaysToExpiry; DWORD DaysToCheck; LARGE_INTEGER Now; LARGE_INTEGER Last; PLARGE_INTEGER StartTime;
if (pGlobals->TransderedCredentials) {
// do not display password expiry in this case as it
// would otherwise display the password expiry twice
return FALSE; }
Last.LowPart = pGlobals->LastNotification.dwLowDateTime; Last.HighPart = pGlobals->LastNotification.dwHighDateTime;
GetSystemTimeAsFileTime((FILETIME*) &Now);
Last.QuadPart += (24 * 60 * 60 * 10000000I64);
//
// Only if last shown more than 24 hours ago
//
if (Now.QuadPart < Last.QuadPart) { return FALSE; }
//
// Get password expiry warning period
//
DaysToCheck = GetPasswordExpiryWarningPeriod();
//
// Go get parameters from our user's profile
//
if (!pGlobals->Profile) { return FALSE; }
if ( LogonCheck ) { StartTime = &pGlobals->LogonTime; } else { StartTime = &Now; }
//
// Determine number of days till the password expires.
//
if (!GetDaysToExpiry(StartTime, &(pGlobals->Profile->PasswordMustChange), &DaysToExpiry)) { return FALSE; } // Not within warning period?
if (DaysToExpiry > DaysToCheck) { return FALSE; }
// If return pointer... fill in
if ( pDaysToExpiry ) { *pDaysToExpiry = DaysToExpiry; }
return TRUE; }
//+---------------------------------------------------------------------------
//
// Function: CheckPasswordExpiry
//
// Synopsis: Does the password expiration check on demand
//
// Arguments: [pGlobals] --
// [LogonCheck] --
//
// Requires:
//
// Returns:
//
// Signals:
//
// Modifies:
//
// Algorithm:
//
// History: 8-13-96 RichardW Created
//
// Notes:
//
//----------------------------------------------------------------------------
INT_PTR CheckPasswordExpiry( PGLOBALS pGlobals, BOOL LogonCheck) { LARGE_INTEGER Now; ULONG DaysToExpiry; TCHAR Buffer1[MAX_STRING_BYTES]; TCHAR Buffer2[MAX_STRING_BYTES]; INT_PTR Result = IDOK; LPTSTR UserSidString;
// Get current time
GetSystemTimeAsFileTime((FILETIME*) &Now);
if (ShouldPasswordExpiryWarningBeShown(pGlobals, LogonCheck, &DaysToExpiry)) { //
// Disable optimized logon for this user for next time if
// we are entering the password expiry warning period, so
// password expiry warning dialogs will be shown if the user
// does not change the password right now. Otherwise
// for cached logons password expiry time is invented to be
// forever in the future.
//
if (pGlobals->UserProcessData.UserToken) { UserSidString = GcGetSidString(pGlobals->UserProcessData.UserToken);
if (UserSidString) { GcSetNextLogonCacheable(UserSidString, FALSE); GcDeleteSidString(UserSidString); } } if (DaysToExpiry > 0) { LoadString(hDllInstance, IDS_PASSWORD_WILL_EXPIRE, Buffer1, sizeof(Buffer1) / sizeof( TCHAR )); _snwprintf(Buffer2, sizeof(Buffer2)/sizeof(TCHAR) - 1, Buffer1, DaysToExpiry); Buffer2[sizeof(Buffer2)/sizeof(TCHAR) - 1] = 0; } else { LoadString(hDllInstance, IDS_PASSWORD_EXPIRES_TODAY, Buffer2, sizeof(Buffer2) / sizeof( TCHAR )); }
LoadString(hDllInstance, IDS_LOGON_MESSAGE, Buffer1, sizeof(Buffer1) / sizeof( TCHAR ) );
pGlobals->LastNotification.dwHighDateTime = Now.HighPart; pGlobals->LastNotification.dwLowDateTime = Now.LowPart;
Result = TimeoutMessageBoxlpstr(NULL, pGlobals, Buffer2, Buffer1, MB_YESNO | MB_ICONEXCLAMATION, (LogonCheck ? LOGON_TIMEOUT : 60)); if (Result == IDYES) { //
// Let the user change their password now
//
if ( LogonCheck && pGlobals->SmartCardLogon ) { LogonCheck = FALSE ; }
if ( LogonCheck ) { RevealPassword( &pGlobals->PasswordString );
Result = ChangePasswordLogon(NULL, pGlobals, pGlobals->UserName, pGlobals->Domain, pGlobals->Password);
if ( Result == IDCANCEL ) { //
// If we got cancelled, then the string won't get
// updated, so rehide it so that unlocks work later
//
HidePassword( &pGlobals->Seed, &pGlobals->PasswordString ); }
} else { Result = ChangePassword( NULL, pGlobals, pGlobals->UserName, pGlobals->Domain, CHANGEPWD_OPTION_ALL );
}
}
if (DLG_INTERRUPTED(Result)) { return(Result); } }
return MSGINA_DLG_SUCCESS; }
/****************************************************************************\
* * FUNCTION: DisplayPostShellLogonMessages * * PURPOSE: Displays any security warnings to the user after a successful logon * The messages are displayed while the shell is starting up. * * RETURNS: DLG_SUCCESS - the dialogs were displayed successfully. * DLG_INTERRUPTED() - a set defined in winlogon.h * * NOTE: Screen-saver timeouts are handled by our parent dialog so this * routine should never return DLG_SCREEN_SAVER_TIMEOUT * * HISTORY: * * 12-09-91 Davidc Created. * \****************************************************************************/
INT_PTR DisplayPostShellLogonMessages( PGLOBALS pGlobals ) { INT_PTR Result = IDOK;
//
// Check to see if the system time is properly set
//
{ SYSTEMTIME Systime;
GetSystemTime(&Systime);
if ( Systime.wYear < 2000 ) {
Result = TimeoutMessageBox( NULL, pGlobals, IDS_INVALID_TIME_MSG, IDS_INVALID_TIME, MB_OK | MB_ICONSTOP, TIMEOUT_NONE );
if (DLG_INTERRUPTED(Result)) { return(Result); } } }
pGlobals->LastNotification.dwHighDateTime = 0; pGlobals->LastNotification.dwLowDateTime = 0;
if (!pGlobals->TransderedCredentials) {
// do not display password expiry in this case as it
// would otherwise display the password expiry twice
Result = CheckPasswordExpiry( pGlobals, TRUE ); }
if (pGlobals->Profile != NULL) {
//
// Logon cache used
//
if (pGlobals->Profile->UserFlags & LOGON_CACHED_ACCOUNT) {
//
// Don't display any warning messages if we did an optimized logon.
//
if (pGlobals->OptimizedLogonStatus != OLS_LogonIsCached) { DoNoDCDialog( pGlobals ); } } }
return(IDOK); }
INT_PTR PostShellPasswordErase( PGLOBALS pGlobals ) { //
// Hash the password away, then destroy the text copy completely.
//
if (!pGlobals->TransderedCredentials) { RevealPassword( &pGlobals->PasswordString ); if (pGlobals->SmartCardLogon) { // We don't want the SC PIN hash
// (prevents password unlocks using the PIN)
memset(pGlobals->PasswordHash, 0, sizeof(pGlobals->PasswordHash)); } else { HashPassword( &pGlobals->PasswordString, pGlobals->PasswordHash ); } ErasePassword( &pGlobals->PasswordString );
if (pGlobals->OldPasswordPresent) { ErasePassword( &pGlobals->OldPasswordString ); pGlobals->OldPasswordPresent = 0; } }
return(IDOK); }
/***************************************************************************\
* FUNCTION: SetLogonScriptVariables * * PURPOSE: Sets the appropriate environment variables in the user * process environment block so that the logon script information * can be passed into the userinit app. * * RETURNS: TRUE on success, FALSE on failure * * HISTORY: * * 21-Aug-92 Davidc Created. * \***************************************************************************/
BOOL SetLogonScriptVariables( PGLOBALS pGlobals, PVOID * pEnvironment ) { NTSTATUS Status; LPWSTR EncodedMultiSz; UNICODE_STRING Name, Value;
//
// Note whether we performed an optimized logon.
//
RtlInitUnicodeString(&Name, OPTIMIZED_LOGON_VARIABLE);
if (pGlobals->OptimizedLogonStatus == OLS_LogonIsCached) { RtlInitUnicodeString(&Value, L"1"); } else { RtlInitUnicodeString(&Value, L"0"); }
Status = RtlSetEnvironmentVariable(pEnvironment, &Name, &Value); if (!NT_SUCCESS(Status)) { WLPrint(("Failed to set environment variable <%Z> to value <%Z>", &Name, &Value)); goto CleanupAndExit; }
//
// Set our primary authenticator logon script variables
//
if (pGlobals->Profile != NULL) {
//
// Set the server name variable
//
RtlInitUnicodeString(&Name, LOGON_SERVER_VARIABLE); Status = RtlSetEnvironmentVariable(pEnvironment, &Name, &pGlobals->Profile->LogonServer); if (!NT_SUCCESS(Status)) { WLPrint(("Failed to set environment variable <%Z> to value <%Z>", &Name, &pGlobals->Profile->LogonServer)); goto CleanupAndExit; }
//
// Set the script name variable
//
RtlInitUnicodeString(&Name, LOGON_SCRIPT_VARIABLE); Status = RtlSetEnvironmentVariable(pEnvironment, &Name, &pGlobals->Profile->LogonScript); if (!NT_SUCCESS(Status)) { WLPrint(("Failed to set environment variable <%Z> to value <%Z>", &Name, &pGlobals->Profile->LogonScript)); goto CleanupAndExit; } }
//
// Set the multiple provider script name variable
//
if (pGlobals->MprLogonScripts != NULL) {
RtlInitUnicodeString(&Name, MPR_LOGON_SCRIPT_VARIABLE);
EncodedMultiSz = EncodeMultiSzW(pGlobals->MprLogonScripts); if (EncodedMultiSz == NULL) { WLPrint(("Failed to encode MPR logon scripts into a string")); goto CleanupAndExit; }
RtlInitUnicodeString(&Value, EncodedMultiSz); Status = RtlSetEnvironmentVariable(pEnvironment, &Name, &Value); Free(EncodedMultiSz); if (!NT_SUCCESS(Status)) { WLPrint(("Failed to set mpr scripts environment variable <%Z>", &Name)); goto CleanupAndExit; } }
return(TRUE);
CleanupAndExit:
DeleteLogonScriptVariables(pGlobals, pEnvironment); return(FALSE); }
BOOL SetAutoEnrollVariables( PGLOBALS pGlobals, PVOID * pEnvironment ) { BOOL Result = FALSE ; UNICODE_STRING Name, Value ;
// we should check for safe boot, domain member, and policy flag in registry
// but we will always spawn userinit, so instead of duplicationg code, let
// autoenrollment do those checks.
/*
if (OpenHKeyCurrentUser(pGlobals)) {
if ( RegOpenKeyEx( pGlobals->UserProcessData.hCurrentUser, WINLOGON_POLICY_KEY, 0, KEY_READ, &hKey ) == 0 ) { dwSize = sizeof( Result );
RegQueryValueEx( hKey, DISABLE_AUTOENROLLMENT, 0, &dwType, (PBYTE) &Result, &dwSize );
RegCloseKey( hKey );
}
CloseHKeyCurrentUser(pGlobals); } */ //
// If the Disable flag hasn't been turned on, add the env var
//
if ( !Result ) { RtlInitUnicodeString( &Name, USER_INIT_AUTOENROLL ); RtlInitUnicodeString( &Value, AUTOENROLL_NONEXCLUSIVE ); RtlSetEnvironmentVariable(pEnvironment, &Name, &Value);
RtlInitUnicodeString( &Name, USER_INIT_AUTOENROLLMODE ); RtlInitUnicodeString( &Value, AUTOENROLL_STARTUP ); RtlSetEnvironmentVariable(pEnvironment, &Name, &Value); }
return TRUE ; }
/***************************************************************************\
* FUNCTION: DeleteLogonScriptVariables * * PURPOSE: Deletes the environment variables in the user process * environment block that we use to communicate logon script * information to the userinit app * * RETURNS: Nothing * * HISTORY: * * 21-Aug-92 Davidc Created. * \***************************************************************************/
VOID DeleteLogonScriptVariables( PGLOBALS pGlobals, PVOID * pEnvironment ) { NTSTATUS Status; UNICODE_STRING Name;
RtlInitUnicodeString(&Name, OPTIMIZED_LOGON_VARIABLE);
Status = RtlSetEnvironmentVariable(pEnvironment, &Name, NULL); if (!NT_SUCCESS(Status) && (Status != STATUS_UNSUCCESSFUL) ) { WLPrint(("Failed to delete environment variable <%Z>, status = 0x%lx", &Name, Status)); }
RtlInitUnicodeString(&Name, LOGON_SERVER_VARIABLE);
Status = RtlSetEnvironmentVariable(pEnvironment, &Name, NULL); if (!NT_SUCCESS(Status) && (Status != STATUS_UNSUCCESSFUL) ) { WLPrint(("Failed to delete environment variable <%Z>, status = 0x%lx", &Name, Status)); }
RtlInitUnicodeString(&Name, LOGON_SCRIPT_VARIABLE);
Status = RtlSetEnvironmentVariable(pEnvironment, &Name, NULL); if (!NT_SUCCESS(Status) && (Status != STATUS_UNSUCCESSFUL) ) { WLPrint(("Failed to delete environment variable <%Z>, status = 0x%lx", &Name, Status)); }
if (pGlobals->MprLogonScripts != NULL) { RtlInitUnicodeString(&Name, MPR_LOGON_SCRIPT_VARIABLE);
Status = RtlSetEnvironmentVariable(pEnvironment, &Name, NULL); if (!NT_SUCCESS(Status) && (Status != STATUS_UNSUCCESSFUL) ) { WLPrint(("Failed to delete environment variable <%Z>, status = 0x%lx", &Name, Status)); } } }
BOOL WINAPI WlxActivateUserShell( PVOID pWlxContext, PWSTR pszDesktop, PWSTR pszMprLogonScript, PVOID pEnvironment ) { BOOL bExec; PGLOBALS pGlobals; PWSTR pchData; BOOL fReturn = FALSE;
_ShellReleaseLogonMutex(TRUE); pchData = AllocAndGetPrivateProfileString(APPLICATION_NAME, USERINIT_KEY, TEXT("%SystemRoot%\\system32\\userinit.exe"), NULL);
if ( !pchData ) { if (pszMprLogonScript) { LocalFree(pszMprLogonScript); } goto WlxAUSEnd; }
pGlobals = (PGLOBALS) pWlxContext;
if (pGlobals->MprLogonScripts) { LocalFree(pGlobals->MprLogonScripts); }
pGlobals->MprLogonScripts = pszMprLogonScript;
bExec = ExecProcesses(pWlxContext, pszDesktop, pchData, &pEnvironment, 0, 0);
Free( pchData );
if (!bExec && (DebugAllowNoShell == 0)) { goto WlxAUSEnd; }
pGlobals->UserProcessData.pEnvironment = pEnvironment;
// Write out the current user name to a place where shell logoff can read it
if (OpenHKeyCurrentUser(pGlobals)) { HKEY hkeyExplorer = NULL; if (ERROR_SUCCESS == RegOpenKeyEx(pGlobals->UserProcessData.hCurrentUser, SHUTDOWN_SETTING_KEY, 0, KEY_SET_VALUE, &hkeyExplorer)) { RegSetValueEx(hkeyExplorer, LOGON_USERNAME_SETTING, 0, REG_SZ, (CONST BYTE *) pGlobals->UserName, ((lstrlen(pGlobals->UserName) + 1) * sizeof(WCHAR)));
RegCloseKey(hkeyExplorer); }
CloseHKeyCurrentUser(pGlobals); }
fReturn = TRUE ; WlxAUSEnd:
return fReturn;
}
BOOL WINAPI WlxStartApplication( PVOID pWlxContext, PWSTR pszDesktop, PVOID pEnvironment, PWSTR pszCmdLine ) { PROCESS_INFORMATION ProcessInformation; BOOL bExec; PGLOBALS pGlobals = (PGLOBALS) pWlxContext; WCHAR szCurrentDir[MAX_PATH]; WCHAR localApp[ MAX_PATH ];
szCurrentDir[0] = L'\0'; if (pEnvironment) { UpdateUserEnvironment(pGlobals, &pEnvironment, szCurrentDir); }
if ( (_wcsicmp(pszCmdLine, L"explorer.exe" ) == 0 ) || (_wcsicmp(pszCmdLine, L"explorer" ) == 0 ) ) {
//
// Avoid security problem since explorer is in SystemRoot,
// not SystemRoot\system32
//
if ( ExpandEnvironmentStrings( L"%SystemRoot%\\explorer.exe", localApp, MAX_PATH ) != 0 ) {
pszCmdLine = localApp ; } }
bExec = ExecApplication (pszCmdLine, pszDesktop, pGlobals, pEnvironment, 0, STARTF_USESHOWWINDOW, _wcsicmp(pszCmdLine, TEXT("taskmgr.exe")), // don't restrict application
&ProcessInformation);
if (pEnvironment) { // We don't need it anymore
VirtualFree(pEnvironment, 0, MEM_RELEASE); }
if (!bExec) { if ( szCurrentDir[0] ) { SetCurrentDirectory(szCurrentDir); } return(FALSE); }
if (SetProcessQuotas(pGlobals, &ProcessInformation, &pGlobals->UserProcessData)) { ResumeThread(ProcessInformation.hThread); } else { // OK as the process was created suspended
TerminateProcess(ProcessInformation.hProcess, ERROR_ACCESS_DENIED); }
CloseHandle(ProcessInformation.hThread); CloseHandle(ProcessInformation.hProcess);
if ( szCurrentDir[0] ) { SetCurrentDirectory(szCurrentDir); }
return(TRUE); }
void CtxCreateMigrateEnv( PVOID pEnv ) { NTSTATUS Status; UNICODE_STRING Name, Value; DWORD cb;
cb = 1024; Value.Buffer = Alloc(sizeof(TCHAR)*cb);
if (!Value.Buffer) return;
Value.Length = (USHORT)cb; Value.MaximumLength = (USHORT)cb; RtlInitUnicodeString( &Name, HOMEDRIVE_VARIABLE ); Status = RtlQueryEnvironmentVariable_U( pEnv, &Name, &Value ); if ( NT_SUCCESS(Status) ) SetEnvironmentVariable( HOMEDRIVE_VARIABLE, Value.Buffer );
Value.Length = (USHORT)cb; Value.MaximumLength = (USHORT)cb; RtlInitUnicodeString( &Name, HOMEPATH_VARIABLE ); Status = RtlQueryEnvironmentVariable_U( pEnv, &Name, &Value ); if ( NT_SUCCESS(Status) ) SetEnvironmentVariable( HOMEPATH_VARIABLE, Value.Buffer );
Value.Length = (USHORT)cb; Value.MaximumLength = (USHORT)cb; RtlInitUnicodeString( &Name, INIDRIVE_VARIABLE ); Status = RtlQueryEnvironmentVariable_U( pEnv, &Name, &Value ); if ( NT_SUCCESS(Status) ) SetEnvironmentVariable( INIDRIVE_VARIABLE, Value.Buffer );
Value.Length = (USHORT)cb; Value.MaximumLength = (USHORT)cb; RtlInitUnicodeString(&Name, INIPATH_VARIABLE); Status = RtlQueryEnvironmentVariable_U( pEnv, &Name, &Value ); if ( NT_SUCCESS(Status) ) SetEnvironmentVariable( INIPATH_VARIABLE, Value.Buffer );
Free(Value.Buffer); }
void CtxDeleteMigrateEnv( ) { SetEnvironmentVariable( HOMEDRIVE_VARIABLE, NULL); SetEnvironmentVariable( HOMEPATH_VARIABLE, NULL); SetEnvironmentVariable( INIDRIVE_VARIABLE, NULL); SetEnvironmentVariable( INIPATH_VARIABLE, NULL); }
|