Windows-Server-2003/shell/ext/gina/systemsettings.cpp

1145 lines
38 KiB
C++

// --------------------------------------------------------------------------
// Module Name: SystemSettings.cpp
//
// Copyright (c) 1999-2000, Microsoft Corporation
//
// A class to handle opening and reading/writing from the Winlogon key.
//
// History: 1999-09-09 vtan created
// 1999-11-16 vtan separate file
// 2000-02-01 vtan moved from Neptune to Whistler
// --------------------------------------------------------------------------
#include "StandardHeader.h"
#include "SystemSettings.h"
#include <regstr.h>
#include <safeboot.h>
#include <winsta.h>
#include <allproc.h> // TS_COUNTER
#include <shlwapi.h>
#include "RegistryResources.h"
const TCHAR CSystemSettings::s_szSafeModeKeyName[] = TEXT("SYSTEM\\CurrentControlSet\\Control\\SafeBoot\\Option");
const TCHAR CSystemSettings::s_szSafeModeOptionValueName[] = TEXT("OptionValue");
const TCHAR CSystemSettings::s_szWinlogonKeyName[] = TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon");
const TCHAR CSystemSettings::s_szSystemPolicyKeyName[] = TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\policies\\system");
const TCHAR CSystemSettings::s_szTerminalServerKeyName[] = TEXT("SYSTEM\\CurrentControlSet\\Control\\Terminal Server");
const TCHAR CSystemSettings::s_szTerminalServerPolicyKeyName[] = TEXT("SOFTWARE\\Policies\\Microsoft\\Windows NT\\Terminal Services");
const TCHAR CSystemSettings::s_szNetwareClientKeyName[] = TEXT("SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order");
const TCHAR CSystemSettings::s_szLogonTypeValueName[] = TEXT("LogonType");
const TCHAR CSystemSettings::s_szBackgroundValueName[] = TEXT("Background");
const TCHAR CSystemSettings::s_szMultipleUsersValueName[] = TEXT("AllowMultipleTSSessions");
const TCHAR CSystemSettings::s_szDenyRemoteConnectionsValueName[] = TEXT("fDenyTSConnections");
int CSystemSettings::s_iIsSafeModeMinimal = -1;
int CSystemSettings::s_iIsSafeModeNetwork = -1;
// --------------------------------------------------------------------------
// CSystemSettings::IsSafeMode
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Was the machine started in safe mode (minimal or network) ?
//
// History: 2000-03-06 vtan created
// --------------------------------------------------------------------------
bool CSystemSettings::IsSafeMode (void)
{
return(IsSafeModeMinimal() || IsSafeModeNetwork());
}
// --------------------------------------------------------------------------
// CSystemSettings::IsSafeModeMinimal
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Was the machine started in safe mode minimal?
//
// History: 1999-09-13 vtan created
// 2000-05-25 vtan cache result in static member variable
// --------------------------------------------------------------------------
bool CSystemSettings::IsSafeModeMinimal (void)
{
if (-1 == s_iIsSafeModeMinimal)
{
bool fResult;
CRegKey regKey;
fResult = false;
if (ERROR_SUCCESS == regKey.Open(HKEY_LOCAL_MACHINE,
s_szSafeModeKeyName,
KEY_QUERY_VALUE))
{
DWORD dwValue, dwValueSize;
dwValueSize = sizeof(dwValue);
if (ERROR_SUCCESS == regKey.GetDWORD(s_szSafeModeOptionValueName,
dwValue))
{
fResult = (dwValue == SAFEBOOT_MINIMAL);
}
}
s_iIsSafeModeMinimal = fResult;
}
return(s_iIsSafeModeMinimal != 0);
}
// --------------------------------------------------------------------------
// CSystemSettings::IsSafeModeNetwork
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Was the machine started in safe mode with networking?
//
// History: 1999-11-09 vtan created
// 2000-05-25 vtan cache result in static member variable
// --------------------------------------------------------------------------
bool CSystemSettings::IsSafeModeNetwork (void)
{
if (-1 == s_iIsSafeModeNetwork)
{
bool fResult;
CRegKey regKey;
fResult = false;
if (ERROR_SUCCESS == regKey.Open(HKEY_LOCAL_MACHINE,
s_szSafeModeKeyName,
KEY_QUERY_VALUE))
{
DWORD dwValue, dwValueSize;
dwValueSize = sizeof(dwValue);
if (ERROR_SUCCESS == regKey.GetDWORD(s_szSafeModeOptionValueName,
dwValue))
{
fResult = (dwValue == SAFEBOOT_NETWORK);
}
}
s_iIsSafeModeNetwork = fResult;
}
return(s_iIsSafeModeNetwork != 0);
}
// --------------------------------------------------------------------------
// CSystemSettings::IsNetwareActive
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Returns whether this machine is a workstation running
// Netware client services or not.
//
// History: 2001-05-16 cevans created
// --------------------------------------------------------------------------
bool CSystemSettings::IsNetwareActive (void)
{
bool fResult;
LONG lErrorCode;
TCHAR szProviders[MAX_PATH] = {0};
CRegKey regKey;
fResult = false;
lErrorCode = regKey.Open(HKEY_LOCAL_MACHINE,
s_szNetwareClientKeyName,
KEY_QUERY_VALUE);
if (ERROR_SUCCESS == lErrorCode)
{
if((regKey.GetString(TEXT("ProviderOrder"), szProviders, ARRAYSIZE(szProviders)) == ERROR_SUCCESS))
{
if (StrStrI(szProviders, TEXT("NWCWorkstation")) != NULL)
{
fResult = true;
}
else if (StrStrI(szProviders, TEXT("NetwareWorkstation")) != NULL)
{
fResult = true;
}
}
}
return fResult;
}
// --------------------------------------------------------------------------
// CSystemSettings::IsWorkStationProduct
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Returns whether this machine is a workstation product vs.
// a server product.
//
// History: 2000-08-30 vtan created
// --------------------------------------------------------------------------
bool CSystemSettings::IsWorkStationProduct (void)
{
OSVERSIONINFOEXA osVersionInfo;
ZeroMemory(&osVersionInfo, sizeof(osVersionInfo));
osVersionInfo.dwOSVersionInfoSize = sizeof(osVersionInfo);
return((GetVersionExA(reinterpret_cast<OSVERSIONINFOA*>(&osVersionInfo)) != FALSE) &&
(VER_NT_WORKSTATION == osVersionInfo.wProductType));
}
// --------------------------------------------------------------------------
// CSystemSettings::IsDomainMember
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Is this machine a member of a domain? Use the LSA to get this
// information.
//
// History: 1999-09-14 vtan created
// --------------------------------------------------------------------------
bool CSystemSettings::IsDomainMember (void)
{
bool fResult;
int iCounter;
NTSTATUS status;
OBJECT_ATTRIBUTES objectAttributes;
LSA_HANDLE lsaHandle;
SECURITY_QUALITY_OF_SERVICE securityQualityOfService;
PPOLICY_DNS_DOMAIN_INFO pDNSDomainInfo;
fResult = false;
securityQualityOfService.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
securityQualityOfService.ImpersonationLevel = SecurityImpersonation;
securityQualityOfService.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
securityQualityOfService.EffectiveOnly = FALSE;
InitializeObjectAttributes(&objectAttributes, NULL, 0, NULL, NULL);
objectAttributes.SecurityQualityOfService = &securityQualityOfService;
iCounter = 0;
do
{
status = LsaOpenPolicy(NULL, &objectAttributes, POLICY_VIEW_LOCAL_INFORMATION, &lsaHandle);
if (RPC_NT_SERVER_TOO_BUSY == status)
{
Sleep(10);
}
} while ((RPC_NT_SERVER_TOO_BUSY == status) && (++iCounter < 10));
if (NT_SUCCESS(status))
{
status = LsaQueryInformationPolicy(lsaHandle, PolicyDnsDomainInformation, reinterpret_cast<void**>(&pDNSDomainInfo));
if (NT_SUCCESS(status) && (pDNSDomainInfo != NULL))
{
fResult = ((pDNSDomainInfo->DnsDomainName.Length != 0) ||
(pDNSDomainInfo->DnsForestName.Length != 0) ||
(pDNSDomainInfo->Sid != NULL));
TSTATUS(LsaFreeMemory(pDNSDomainInfo));
}
TSTATUS(LsaClose(lsaHandle));
}
return(fResult);
}
// --------------------------------------------------------------------------
// CSystemSettings::IsActiveConsoleSession
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Returns whether current process session is the active console
// session.
//
// History: 2001-03-04 vtan created
// --------------------------------------------------------------------------
bool CSystemSettings::IsActiveConsoleSession (void)
{
return(NtCurrentPeb()->SessionId == USER_SHARED_DATA->ActiveConsoleId);
}
// --------------------------------------------------------------------------
// CSystemSettings::IsTerminalServicesEnabled
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Does this machine have an enabled terminal services service?
// This function is for Windows 2000 and later ONLY.
//
// History: 2000-03-02 vtan created
// --------------------------------------------------------------------------
bool CSystemSettings::IsTerminalServicesEnabled (void)
{
OSVERSIONINFOEX osVersionInfo;
DWORDLONG dwlConditionMask;
dwlConditionMask = 0;
ZeroMemory(&osVersionInfo, sizeof(osVersionInfo));
osVersionInfo.dwOSVersionInfoSize = sizeof(osVersionInfo);
osVersionInfo.wSuiteMask = VER_SUITE_TERMINAL | VER_SUITE_SINGLEUSERTS;
VER_SET_CONDITION(dwlConditionMask, VER_SUITENAME, VER_OR);
return((VerifyVersionInfo(&osVersionInfo, VER_SUITENAME, dwlConditionMask) != FALSE) &&
!IsSCMTerminalServicesDisabled());
}
// --------------------------------------------------------------------------
// CSystemSettings::IsFriendlyUIActive
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Read the registry HKLM\Software\Microsoft\Windows NT\
// CurrentVersion\Winlogon\LogonType and if this value is 0x01
// then activate the external UI host. This function returns the
// setting. This can never be true for domain member machines.
//
// History: 2000-02-04 vtan created
// --------------------------------------------------------------------------
bool CSystemSettings::IsFriendlyUIActive (void)
{
int iResult;
return(IsWorkStationProduct() &&
(!IsDomainMember() || IsForceFriendlyUI()) &&
IsMicrosoftGINA() &&
!IsNetwareActive() &&
(ERROR_SUCCESS == GetEffectiveInteger(HKEY_LOCAL_MACHINE,
s_szWinlogonKeyName,
s_szSystemPolicyKeyName,
s_szLogonTypeValueName,
iResult)) &&
(iResult != 0));
}
// --------------------------------------------------------------------------
// CSystemSettings::IsMultipleUsersEnabled
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Read the registry HKLM\Software\Microsoft\Windows NT\
// CurrentVersion\Winlogon\AllowMultipleTSSessions and if the
// value is 0x01 *AND* terminal services is installed on this
// machine then the conditions are satisfied.
//
// History: 2000-03-02 vtan created
// --------------------------------------------------------------------------
bool CSystemSettings::IsMultipleUsersEnabled (void)
{
int iResult;
return(IsTerminalServicesEnabled() &&
!IsSafeMode() &&
(ERROR_SUCCESS == GetEffectiveInteger(HKEY_LOCAL_MACHINE,
s_szWinlogonKeyName,
s_szSystemPolicyKeyName,
s_szMultipleUsersValueName,
iResult)) &&
(iResult != 0));
}
// --------------------------------------------------------------------------
// CSystemSettings::IsRemoteConnectionsEnabled
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Read the registry HKLM\System\CurrentControlSet\Control\
// Terminal Server\fDenyTSConnections and returns the
// value back to the caller.
//
// History: 2000-07-28 vtan created
// --------------------------------------------------------------------------
bool CSystemSettings::IsRemoteConnectionsEnabled (void)
{
int iResult;
CRegKey regKey;
return(IsTerminalServicesEnabled() &&
(ERROR_SUCCESS == GetEffectiveInteger(HKEY_LOCAL_MACHINE,
s_szTerminalServerKeyName,
s_szTerminalServerPolicyKeyName,
s_szDenyRemoteConnectionsValueName,
iResult)) &&
(iResult == 0));
}
// --------------------------------------------------------------------------
// CSystemSettings::IsRemoteConnectionPresent
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Returns whether there is a remote connection active on the
// current system.
//
// History: 2000-07-28 vtan created
// --------------------------------------------------------------------------
bool CSystemSettings::IsRemoteConnectionPresent (void)
{
bool fRemoteConnectionPresent;
HANDLE hServer;
PLOGONID pLogonID, pLogonIDs;
ULONG ul, ulEntries;
fRemoteConnectionPresent = false;
// Open a connection to terminal services and get the number of sessions.
hServer = WinStationOpenServerW(reinterpret_cast<WCHAR*>(SERVERNAME_CURRENT));
if (hServer != NULL)
{
if (WinStationEnumerate(hServer, &pLogonIDs, &ulEntries) != FALSE)
{
// Iterate the sessions looking for active and shadow sessions only.
for (ul = 0, pLogonID = pLogonIDs; !fRemoteConnectionPresent && (ul < ulEntries); ++ul, ++pLogonID)
{
if ((pLogonID->State == State_Active) || (pLogonID->State == State_Shadow))
{
fRemoteConnectionPresent = (lstrcmpi(pLogonID->WinStationName, TEXT("console")) != 0);
}
}
// Free any resources used.
(BOOLEAN)WinStationFreeMemory(pLogonIDs);
}
(BOOLEAN)WinStationCloseServer(hServer);
}
// Return result.
return(fRemoteConnectionPresent);
}
// --------------------------------------------------------------------------
// CSystemSettings::IsShutdownWithoutLogonAllowed
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Read the registry HKLM\Software\Microsoft\Windows NT\
// CurrentVersion\Winlogon\ShutdownWithoutLogon and returns the
// value back to the caller.
//
// History: 2000-04-27 vtan created
// --------------------------------------------------------------------------
bool CSystemSettings::IsShutdownWithoutLogonAllowed (void)
{
int iResult;
return((ERROR_SUCCESS == GetEffectiveInteger(HKEY_LOCAL_MACHINE,
s_szWinlogonKeyName,
s_szSystemPolicyKeyName,
TEXT("ShutdownWithoutLogon"),
iResult)) &&
(iResult != 0));
}
// --------------------------------------------------------------------------
// CSystemSettings::IsUndockWithoutLogonAllowed
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Read the registry HKLM\Software\Microsoft\Windows NT\
// CurrentVersion\Winlogon\UndockWithoutLogon and returns the
// value back to the caller.
//
// History: 2001-03-17 vtan created
// --------------------------------------------------------------------------
bool CSystemSettings::IsUndockWithoutLogonAllowed (void)
{
int iResult;
return((ERROR_SUCCESS == GetEffectiveInteger(HKEY_LOCAL_MACHINE,
s_szWinlogonKeyName,
s_szSystemPolicyKeyName,
REGSTR_VAL_UNDOCK_WITHOUT_LOGON,
iResult)) &&
(iResult != 0));
}
// --------------------------------------------------------------------------
// CSystemSettings::IsForceFriendlyUI
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Read the registry HKLM\Software\Microsoft\Windows NT\
// CurrentVersion\Winlogon\ForceFriendlyUI and returns the
// value back to the caller.
//
// History: 2000-04-27 vtan created
// --------------------------------------------------------------------------
bool CSystemSettings::IsForceFriendlyUI (void)
{
int iResult;
return((ERROR_SUCCESS == GetEffectiveInteger(HKEY_LOCAL_MACHINE,
s_szWinlogonKeyName,
s_szSystemPolicyKeyName,
TEXT("ForceFriendlyUI"),
iResult)) &&
(iResult != 0));
}
// --------------------------------------------------------------------------
// CSystemSettings::GetUIHost
//
// Arguments: pszPath = TCHAR array to receive UI host path.
//
// Returns: LONG
//
// Purpose: Read the registry HKLM\Software\Microsoft\Windows NT\
// CurrentVersion\Winlogon\UIHost and returns the value.
//
// History: 2000-04-12 vtan created
// --------------------------------------------------------------------------
LONG CSystemSettings::GetUIHost (TCHAR *pszPath)
{
return(GetEffectivePath(HKEY_LOCAL_MACHINE,
s_szWinlogonKeyName,
s_szSystemPolicyKeyName,
TEXT("UIHost"),
pszPath));
}
// --------------------------------------------------------------------------
// CSystemSettings::IsUIHostStatic
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Read the registry HKLM\Software\Microsoft\Windows NT\
// CurrentVersion\Winlogon\UIHostStatic and returns the
// value.
//
// History: 2000-04-12 vtan created
// --------------------------------------------------------------------------
bool CSystemSettings::IsUIHostStatic (void)
{
int iResult;
return((ERROR_SUCCESS == GetEffectiveInteger(HKEY_LOCAL_MACHINE,
s_szWinlogonKeyName,
s_szSystemPolicyKeyName,
TEXT("UIHostStatic"),
iResult)) &&
(iResult != 0));
}
// --------------------------------------------------------------------------
// CSystemSettings::EnableFriendlyUI
//
// Arguments: fEnable = Enable friendly UI.
//
// Returns: bool
//
// Purpose: Enable friendly UI. This should only be allowed on workgroup
// machines. Check the machine status to enforce this.
//
// ERROR_NOT_SUPPORTED is returned when the machine is joined to
// a domain.
//
// History: 2000-08-01 vtan created
// --------------------------------------------------------------------------
bool CSystemSettings::EnableFriendlyUI (bool fEnable)
{
LONG lErrorCode;
if (!IsDomainMember() || !fEnable)
{
CRegKey regKey;
lErrorCode = regKey.Open(HKEY_LOCAL_MACHINE,
s_szWinlogonKeyName,
KEY_SET_VALUE);
if (ERROR_SUCCESS == lErrorCode)
{
lErrorCode = regKey.SetDWORD(s_szLogonTypeValueName,
fEnable);
if (fEnable)
{
lErrorCode = regKey.SetString(s_szBackgroundValueName,
TEXT("0 0 0"));
}
else
{
(LONG)regKey.DeleteValue(s_szBackgroundValueName);
}
}
}
else
{
lErrorCode = ERROR_NOT_SUPPORTED;
}
SetLastError(static_cast<DWORD>(lErrorCode));
return(ERROR_SUCCESS == lErrorCode);
}
// --------------------------------------------------------------------------
// CSystemSettings::EnableMultipleUsers
//
// Arguments: fEnable = Enable multiple users.
//
// Returns: bool
//
// Purpose: Enable the multiple users feature. This sets
// AllowMultipleTSSessions to 1 but only does so if remote
// connections are disabled. This allows multiple console
// sessions but no remote sessions. If there is a remote
// connection active this call is rejected.
//
// ERROR_ACCESS_DENIED is returned when there are more than one
// users active and being disabled.
//
// ERROR_CTX_NOT_CONSOLE is returned when being disabled from
// a remote session (disabling only allowed from the console).
//
// ERROR_NOT_SUPPORTED is returned when being disabled from
// the console, remote connections are enabled, and the current
// session is not session 0.
//
// History: 2000-07-28 vtan created
// --------------------------------------------------------------------------
bool CSystemSettings::EnableMultipleUsers (bool fEnable)
{
LONG lErrorCode;
// If disabling multiple users with more than one users active
// reject the call. Return ERROR_ACCESS_DENIED.
if (!fEnable && (GetLoggedOnUserCount() > 1))
{
lErrorCode = ERROR_ACCESS_DENIED;
}
// If disabling and not on the console, reject the call.
// Return ERROR_CTX_NOT_CONSOLE.
else if (!fEnable && !IsActiveConsoleSession())
{
lErrorCode = ERROR_CTX_NOT_CONSOLE;
}
// If disabling from the console and remote connections are enabled and
// the current session is not session 0, reject the call. Otherwise, a
// a remote connection with FUS disabled causes strange results because
// it expects to connect to session 0.
// Return ERROR_NOT_SUPPORTED.
else if (!fEnable && IsRemoteConnectionsEnabled() && NtCurrentPeb()->SessionId != 0)
{
lErrorCode = ERROR_NOT_SUPPORTED;
}
else
{
CRegKey regKey;
lErrorCode = regKey.Open(HKEY_LOCAL_MACHINE,
s_szWinlogonKeyName,
KEY_SET_VALUE);
if (ERROR_SUCCESS == lErrorCode)
{
lErrorCode = regKey.SetDWORD(s_szMultipleUsersValueName,
fEnable);
if (ERROR_SUCCESS == lErrorCode)
{
(DWORD)AdjustFUSCompatibilityServiceState(NULL);
}
}
}
SetLastError(static_cast<DWORD>(lErrorCode));
return(ERROR_SUCCESS == lErrorCode);
}
// --------------------------------------------------------------------------
// CSystemSettings::EnableRemoteConnections
//
// Arguments: fEnable = Enable remote connections.
//
// Returns: bool
//
// Purpose: Enable the remote connections feature. This sets
// fDenyTSConnections to 0 but only does so if there is a one
// user logged onto the system. This allows the single
// connection to be remotely connected but not allow multiple
// console sessions. This conforms to the single user per CPU
// license of the workstation product. To get multiple users
// you need the server product.
//
// ERROR_NOT_SUPPORTED is returned when enabling remote
// connections with FUS disabled and the current session != 0.
//
// History: 2000-07-28 vtan created
// --------------------------------------------------------------------------
bool CSystemSettings::EnableRemoteConnections (bool fEnable)
{
LONG lErrorCode;
// If enabling remote connections, FUS is disabled, and we are not on
// session 0 (can happen immediately after disabling FUS), then a remote
// connection will fail. With FUS disabled, the connection must go to
// session 0. This is a fringe case, but disallow enabling remote
// connections if it happens.
if (fEnable && !IsMultipleUsersEnabled() && NtCurrentPeb()->SessionId != 0)
{
lErrorCode = ERROR_NOT_SUPPORTED;
}
else
{
CRegKey regKey;
lErrorCode = regKey.Open(HKEY_LOCAL_MACHINE,
s_szTerminalServerKeyName,
KEY_SET_VALUE);
if (ERROR_SUCCESS == lErrorCode)
{
lErrorCode = regKey.SetDWORD(s_szDenyRemoteConnectionsValueName,
!fEnable);
}
}
SetLastError(static_cast<DWORD>(lErrorCode));
return(ERROR_SUCCESS == lErrorCode);
}
// --------------------------------------------------------------------------
// CSystemSettings::GetLoggedOnUserCount
//
// Arguments: <none>
//
// Returns: int
//
// Purpose: Returns the count of logged on users on this machine. Ripped
// straight out of shtdndlg.c in msgina.
//
// History: 2000-03-29 vtan created
// 2000-04-21 vtan copied from taskmgr
// 2000-07-28 vtan moved from userlist.cpp
// --------------------------------------------------------------------------
int CSystemSettings::GetLoggedOnUserCount (void)
{
int iCount;
HANDLE hServer;
iCount = 0;
// Open a connection to terminal services and get the number of sessions.
hServer = WinStationOpenServerW(reinterpret_cast<WCHAR*>(SERVERNAME_CURRENT));
if (hServer != NULL)
{
TS_COUNTER tsCounters[2] = {0};
tsCounters[0].counterHead.dwCounterID = TERMSRV_CURRENT_DISC_SESSIONS;
tsCounters[1].counterHead.dwCounterID = TERMSRV_CURRENT_ACTIVE_SESSIONS;
if (WinStationGetTermSrvCountersValue(hServer, ARRAYSIZE(tsCounters), tsCounters))
{
int i;
for (i = 0; i < ARRAYSIZE(tsCounters); i++)
{
if (tsCounters[i].counterHead.bResult)
{
iCount += tsCounters[i].dwValue;
}
}
}
(BOOLEAN)WinStationCloseServer(hServer);
}
// Return result.
return(iCount);
}
// --------------------------------------------------------------------------
// CSystemSettings::CheckDomainMembership
//
// Arguments: <none>
//
// Returns: NTSTATUS
//
// Purpose: Checks the consistency of domain membership and allowing
// multiple TS sessions. The check is only for domain membership
// true not false.
//
// History: 2000-04-12 vtan created
// --------------------------------------------------------------------------
NTSTATUS CSystemSettings::CheckDomainMembership (void)
{
if (IsDomainMember() && !IsForceFriendlyUI() && IsProfessionalTerminalServer())
{
TBOOL(EnableFriendlyUI(false));
(BOOL)EnableMultipleUsers(false);
}
return(STATUS_SUCCESS);
}
// --------------------------------------------------------------------------
// CSystemSettings::AdjustFUSCompatibilityServiceState
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: Turns on or off the FUS compatbility service based on the
// FUS configuration.
//
// History: 2001-02-12 vtan created
// --------------------------------------------------------------------------
DWORD WINAPI CSystemSettings::AdjustFUSCompatibilityServiceState (void *pV)
{
UNREFERENCED_PARAMETER(pV);
#ifdef _X86_
if (IsWorkStationProduct())
{
bool fMultipleUsersEnabled;
SC_HANDLE hSCManager;
fMultipleUsersEnabled = IsMultipleUsersEnabled();
// Connect to the service control manager.
hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (hSCManager != NULL)
{
SC_HANDLE hSCService;
// Open the "FastUserSwitchingCompatibility" service.
hSCService = OpenService(hSCManager,
TEXT("FastUserSwitchingCompatibility"),
SERVICE_START | SERVICE_STOP | SERVICE_QUERY_STATUS);
if (hSCService != NULL)
{
SERVICE_STATUS serviceStatus;
// Find out the status of the service.
if (QueryServiceStatus(hSCService, &serviceStatus) != FALSE)
{
if (fMultipleUsersEnabled && (serviceStatus.dwCurrentState == SERVICE_STOPPED))
{
// If it's supposed to be started and it is not
// running then start the service. This can fail
// because the service is set to disabled. Ignore it.
(BOOL)StartService(hSCService, 0, NULL);
}
else if (!fMultipleUsersEnabled && (serviceStatus.dwCurrentState == SERVICE_RUNNING))
{
// If it's supposed to be stopped and it is
// running then stop the service.
TBOOL(ControlService(hSCService, SERVICE_CONTROL_STOP, &serviceStatus));
}
}
TBOOL(CloseServiceHandle(hSCService));
}
TBOOL(CloseServiceHandle(hSCManager));
}
}
#endif /* _X86_ */
return(0);
}
// --------------------------------------------------------------------------
// CSystemSettings::GetEffectiveInteger
//
// Arguments: hKey = HKEY to read.
// pszKeyName = Subkey name to read.
// pszPolicyKeyName = Policy subkey name to read.
// pszValueName = Value name in subkey to read.
// iResult = int result.
//
// Returns: LONG
//
// Purpose: Reads the effective setting from the registry. The effective
// setting is whatever the user chooses as the regular setting
// overriden by policy. The policy setting is always returned if
// present.
//
// History: 2000-04-12 vtan created
// --------------------------------------------------------------------------
LONG CSystemSettings::GetEffectiveInteger (HKEY hKey, const TCHAR *pszKeyName, const TCHAR *pszPolicyKeyName, const TCHAR *pszValueName, int& iResult)
{
CRegKey regKey;
// Start with a typical initialized value.
iResult = 0;
// First check the regular location.
if (ERROR_SUCCESS == regKey.Open(hKey,
pszKeyName,
KEY_QUERY_VALUE))
{
(LONG)regKey.GetInteger(pszValueName, iResult);
}
// Then check the policy.
if (ERROR_SUCCESS == regKey.Open(hKey,
pszPolicyKeyName,
KEY_QUERY_VALUE))
{
(LONG)regKey.GetInteger(pszValueName, iResult);
}
// Always return ERROR_SUCCESS.
return(ERROR_SUCCESS);
}
// --------------------------------------------------------------------------
// CSystemSettings::GetEffectivePath
//
// Arguments: hKey = HKEY to read.
// pszKeyName = Subkey name to read.
// pszPolicyKeyName = Policy subkey name to read.
// pszValueName = Value name in subkey to read.
// pszPath = TCHAR array to receive effect path.
//
// Returns: LONG
//
// Purpose: Reads the effective setting from the registry. The effective
// setting is whatever the user chooses as the regular setting
// overriden by policy. The policy setting is always returned if
// present. The buffer must be at least MAX_PATH characters.
//
// History: 2000-04-12 vtan created
// --------------------------------------------------------------------------
LONG CSystemSettings::GetEffectivePath (HKEY hKey, const TCHAR *pszKeyName, const TCHAR *pszPolicyKeyName, const TCHAR *pszValueName, TCHAR *pszPath)
{
LONG lErrorCode;
if (IsBadWritePtr(pszPath, MAX_PATH * sizeof(TCHAR)))
{
lErrorCode = ERROR_INVALID_PARAMETER;
}
else
{
LONG lPolicyErrorCode;
CRegKey regKey;
// Start with a typical initialized value.
*pszPath = TEXT('\0');
// First check the regular location.
lErrorCode = regKey.Open(hKey,
pszKeyName,
KEY_QUERY_VALUE);
if (ERROR_SUCCESS == lErrorCode)
{
lErrorCode = regKey.GetPath(pszValueName,
pszPath);
}
// Then check the policy.
lPolicyErrorCode = regKey.Open(hKey,
pszPolicyKeyName,
KEY_QUERY_VALUE);
if (ERROR_SUCCESS == lPolicyErrorCode)
{
lPolicyErrorCode = regKey.GetPath(pszValueName,
pszPath);
}
// If either error code is ERROR_SUCCESS then return that
// error code. Otherwise return the non policy error code.
if ((ERROR_SUCCESS == lErrorCode) || (ERROR_SUCCESS == lPolicyErrorCode))
{
lErrorCode = ERROR_SUCCESS;
}
}
return(lErrorCode);
}
// --------------------------------------------------------------------------
// CSystemSettings::IsProfessionalTerminalServer
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Returns whether this machine is a personal terminal server.
// That is workstation with single user TS.
//
// History: 2000-08-09 vtan created
// --------------------------------------------------------------------------
bool CSystemSettings::IsProfessionalTerminalServer (void)
{
OSVERSIONINFOEX osVersion;
ZeroMemory(&osVersion, sizeof(osVersion));
osVersion.dwOSVersionInfoSize = sizeof(osVersion);
return((GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&osVersion)) != FALSE) &&
(osVersion.wProductType == VER_NT_WORKSTATION) &&
((osVersion.wSuiteMask & VER_SUITE_PERSONAL) == 0) &&
((osVersion.wSuiteMask & VER_SUITE_SINGLEUSERTS) != 0));
}
// --------------------------------------------------------------------------
// CSystemSettings::IsMicrosoftGINA
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Returns whether the current GINA is the Microsoft GINA.
//
// History: 2001-01-05 vtan created
// --------------------------------------------------------------------------
bool CSystemSettings::IsMicrosoftGINA (void)
{
bool fResult;
LONG lErrorCode;
TCHAR szGinaDLL[MAX_PATH];
CRegKey regKey;
fResult = true;
lErrorCode = regKey.Open(HKEY_LOCAL_MACHINE,
s_szWinlogonKeyName,
KEY_QUERY_VALUE);
if (ERROR_SUCCESS == lErrorCode)
{
fResult = (regKey.GetString(TEXT("GinaDLL"), szGinaDLL, ARRAYSIZE(szGinaDLL)) != ERROR_SUCCESS);
}
return(fResult);
}
// --------------------------------------------------------------------------
// CSystemSettings::IsSCMTerminalServicesDisabled
//
// Arguments: <none>
//
// Returns: bool
//
// Purpose: Returns whether terminal services is disabled via the service
// control manager.
//
// History: 2001-04-13 vtan created
// --------------------------------------------------------------------------
bool CSystemSettings::IsSCMTerminalServicesDisabled (void)
{
bool fResult;
SC_HANDLE hSCManager;
fResult = false;
hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (hSCManager != NULL)
{
SC_HANDLE hSCService;
hSCService = OpenService(hSCManager,
TEXT("TermService"),
SERVICE_QUERY_CONFIG);
if (hSCService != NULL)
{
DWORD dwBytesNeeded;
QUERY_SERVICE_CONFIG *pQueryServiceConfig;
(BOOL)QueryServiceConfig(hSCService, NULL, 0, &dwBytesNeeded);
pQueryServiceConfig = static_cast<QUERY_SERVICE_CONFIG*>(LocalAlloc(LMEM_FIXED, dwBytesNeeded));
if (pQueryServiceConfig != NULL)
{
fResult = ((QueryServiceConfig(hSCService,
pQueryServiceConfig,
dwBytesNeeded,
&dwBytesNeeded) != FALSE) &&
(pQueryServiceConfig->dwStartType == SERVICE_DISABLED));
(HLOCAL)LocalFree(pQueryServiceConfig);
}
TBOOL(CloseServiceHandle(hSCService));
}
TBOOL(CloseServiceHandle(hSCManager));
}
return(fResult);
}