windows-nt/Source/XPSP1/NT/termsrv/setup/tstst/tstst.cpp

1561 lines
42 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
// Copyright (c) 1998 - 1999 Microsoft Corporation
#include "stdafx.h"
#include <iostream.h>
#include <fstream.h>
#include <strstrea.h>
#include <dsrole.h>
//
// global utilities and veraibles.
//
char szOutput[2048];
ostrstream szMoreInfo(szOutput, 4096);
TCHAR *ReturnBuffer()
{
static TCHAR szReturnTchar[512];
return szReturnTchar;
}
const OSVERSIONINFOEX *GetOSVersionInfo()
{
static OSVERSIONINFOEX gOsVersion;
static bGotOnce = FALSE;
if (!bGotOnce)
{
ZeroMemory(&gOsVersion, sizeof(OSVERSIONINFOEX));
gOsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
GetVersionEx( (LPOSVERSIONINFO ) &gOsVersion);
bGotOnce = TRUE;
}
return &gOsVersion;
}
// #include <strstream>
#include "winsock2.h"
// ostringstream sz
#ifndef UNREFERENCED_PARAMETER
#define UNREFERENCED_PARAMETER(P) (P)
#endif
#define OLD_VER_SET_CONDITION(_m_,_t_,_c_) _m_=(_m_|(_c_<<(1<<_t_)))
BOOL CheckifBinaryisSigned (TCHAR *szFile); // from tscert.cpp
BOOL EnumerateLicenseServers (); // from timebomb.cpp
TCHAR *IsBetaSystem ();
BOOL HasLicenceGracePeriodExpired (); // from timebomb.cpp
BOOL ExtractAllTSEvents();
BOOL ValidateProductSuite (LPSTR SuiteName);
BOOL IsTerminalServicesEnabled ( VOID );
DWORD IsStringInMultiString(HKEY hkey, LPCTSTR szkey, LPCTSTR szvalue, LPCTSTR szCheckForString, BOOL *pbFound);
BOOL DoesHydraKeysExists ();
TCHAR *IsServer ();
BOOL IsKernelTSEnable ();
BOOL TSEnabled ();
BOOL DoesProductSuiteContainTS ();
BOOL IsTerminalServerRegistryOk ();
TCHAR *IsTerminalServiceStartBitSet ();
BOOL IsTermDDStartBitSet ();
BOOL GetTSOCLogFileName (char *strFileName, UINT uiSize);
BOOL DidTsOCgetCompleteInstallationMessage ();
BOOL FileExists (char *pszFullNameAndPath);
BOOL IsTSOClogPresent ();
BOOL DidOCMInstallTSEnable();
TCHAR *IsClusteringInstalled ();
BOOL IsRemoteAdminMode ();
BOOL CheckModeRegistry (BOOL bAppCompat);
BOOL IsTerminalServiceRunning ();
BOOL CheckVideoKeys ();
BOOL CheckModePermissions(DWORD *pdwSecurtyMode);
BOOL IsFile128Bit(LPTSTR szFile, BOOL *pb128Bit);
ULONG RDPDRINST_DetectInstall(); // defined in drdetect.cpp
BOOL IsAudioOk( VOID );
TCHAR *aszStack[] = {
// _T("noexport\%SystemRoot%\\system32\\drivers\\rdpwdd.sys"),
_T("%SystemRoot%\\system32\\drivers\\termdd.sys"),
_T("%SystemRoot%\\system32\\drivers\\tdasync.sys"),
_T("%SystemRoot%\\system32\\drivers\\tdipx.sys"),
_T("%SystemRoot%\\system32\\drivers\\tdnetb.sys"),
_T("%SystemRoot%\\system32\\drivers\\tdpipe.sys"),
_T("%SystemRoot%\\system32\\drivers\\tdspx.sys"),
_T("%SystemRoot%\\system32\\drivers\\tdtcp.sys"),
_T("%SystemRoot%\\system32\\drivers\\rdpwd.sys"),
_T("%SystemRoot%\\system32\\rdpdd.dll"),
_T("%SystemRoot%\\system32\\rdpwsx.dll")
};
TCHAR Version[256];
TCHAR *GetTSVersion()
{
CRegistry oRegTermsrv;
DWORD cbVersion = 0;
LPTSTR szVersion = NULL;
if ((ERROR_SUCCESS == oRegTermsrv.OpenKey(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Control\\Terminal Server"), KEY_READ)) &&
(ERROR_SUCCESS == oRegTermsrv.ReadRegString(_T("ProductVersion"), &szVersion, &cbVersion)))
{
_tcscpy(Version, szVersion);
return Version;
}
return _T("Error finding Version.");
}
BOOL IsIt50TS()
{
return (0 == _tcsicmp(Version, _T("5.0")));
}
BOOL IsIt51TS()
{
return (0 == _tcsicmp(Version, _T("5.1")));
}
TCHAR *IsLicenceGracePeriodOk ()
{
return (HasLicenceGracePeriodExpired () ? _T("Yep, Its expired") : _T("Its Not expired"));
}
BOOL Check_termdd()
{
return CheckifBinaryisSigned(_T("%SystemRoot%\\system32\\drivers\\termdd.sys"));
}
BOOL Check_tdasync()
{
return CheckifBinaryisSigned(_T("%SystemRoot%\\system32\\drivers\\tdasync.sys"));
}
BOOL Check_tdipx()
{
return CheckifBinaryisSigned(_T("%SystemRoot%\\system32\\drivers\\tdipx.sys"));
}
BOOL Check_tdnetb()
{
return CheckifBinaryisSigned(_T("%SystemRoot%\\system32\\drivers\\tdnetb.sys"));
}
BOOL Check_tdpipe()
{
return CheckifBinaryisSigned(_T("%SystemRoot%\\system32\\drivers\\tdpipe.sys"));
}
BOOL Check_tdspx()
{
return CheckifBinaryisSigned(_T("%SystemRoot%\\system32\\drivers\\tdspx.sys"));
}
BOOL Check_tdtcp()
{
return CheckifBinaryisSigned(_T("%SystemRoot%\\system32\\drivers\\tdtcp.sys"));
}
BOOL Check_rdpwd()
{
return CheckifBinaryisSigned(_T("%SystemRoot%\\system32\\drivers\\rdpwd.sys"));
}
BOOL Check_rdpdd()
{
return CheckifBinaryisSigned(_T("%SystemRoot%\\system32\\rdpdd.dll"));
}
BOOL Check_rdpwsx()
{
return CheckifBinaryisSigned(_T("%SystemRoot%\\system32\\rdpwsx.dll"));
}
BOOL IsRdpDrInstalledProperly ()
{
return RDPDRINST_DetectInstall();
}
TCHAR *GetModePermissions()
{
CRegistry reg;
DWORD dwSecurityMode;
if ( ERROR_SUCCESS == reg.OpenKey( HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Control\\Terminal Server"), KEY_READ))
{
if ( ERROR_SUCCESS == reg.ReadRegDWord( _T("TSUserEnabled"), &dwSecurityMode))
{
if (dwSecurityMode == 0)
{
return _T("Its W2k Compatible");
}
else if (dwSecurityMode == 1)
{
return _T("Its TS4 Compatible");
}
else
{
szMoreInfo << "SYSTEM\\CurrentControlSet\\Control\\Terminal Server/TSUserEnabled has wrong value" << dwSecurityMode << endl;
return NULL;
}
}
}
return NULL;
}
BOOL CheckModePermissions (DWORD *pdwSecurtyMode)
{
// PERM_WIN2K = 0,
// PERM_TS4 = 1
CRegistry reg;
if ( ERROR_SUCCESS == reg.OpenKey( HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Control\\Terminal Server"), KEY_READ))
{
if ( ERROR_SUCCESS == reg.ReadRegDWord( _T("TSUserEnabled"), pdwSecurtyMode))
{
return (*pdwSecurtyMode== 0) || (*pdwSecurtyMode== 1);
}
}
return FALSE;
}
TCHAR *GetCypherStrenthOnRdpwd ()
{
BOOL bFile128bit;
if ( IsFile128Bit(_T("%SystemRoot%\\system32\\drivers\\rdpwd.sys"), &bFile128bit) )
{
return bFile128bit ? _T("128 Bit") : _T("56 Bit");
}
else
{
return NULL;
}
}
BOOL IsFile128Bit(LPTSTR szFile, BOOL *pb128Bit)
{
USES_CONVERSION;
DWORD dwHandle;
TCHAR szFullFile[MAX_PATH +1];
BOOL bSuccess = FALSE;
if (ExpandEnvironmentStrings(szFile, szFullFile, MAX_PATH))
{
if (FileExists(T2A(szFullFile)))
{
DWORD dwSize = GetFileVersionInfoSize(szFullFile, &dwHandle);
if (dwSize > 0)
{
BYTE *pbData = new BYTE[dwSize];
if (pbData)
{
if (GetFileVersionInfo(szFullFile, 0, dwSize, pbData))
{
TCHAR *szFileDescription;
UINT uiLen = 0;
if (VerQueryValue(pbData, _T("\\StringFileInfo\\040904B0\\FileDescription"), (LPVOID *)&szFileDescription, &uiLen))
{
if (_tcsstr(szFileDescription, _T("Not for Export")))
{
*pb128Bit = TRUE;
bSuccess = TRUE;
}
else if (_tcsstr(szFileDescription, _T("Export Version")))
{
*pb128Bit = FALSE;
bSuccess = TRUE;
}
}
}
delete [] pbData;
}
}
}
}
return bSuccess;
}
BOOL ValidateProductSuite (LPSTR SuiteName)
{
BOOL rVal = FALSE;
LONG Rslt;
HKEY hKey = NULL;
DWORD Type = 0;
DWORD Size = 0;
LPSTR ProductSuite = NULL;
LPSTR p;
Rslt = RegOpenKeyA(
HKEY_LOCAL_MACHINE,
"System\\CurrentControlSet\\Control\\ProductOptions",
&hKey
);
if (Rslt != ERROR_SUCCESS)
goto exit;
Rslt = RegQueryValueExA( hKey, "ProductSuite", NULL, &Type, NULL, &Size );
if (Rslt != ERROR_SUCCESS || !Size)
goto exit;
ProductSuite = (LPSTR) LocalAlloc( LPTR, Size );
if (!ProductSuite)
goto exit;
Rslt = RegQueryValueExA( hKey, "ProductSuite", NULL, &Type,
(LPBYTE) ProductSuite, &Size );
if (Rslt != ERROR_SUCCESS || Type != REG_MULTI_SZ)
goto exit;
p = ProductSuite;
while (*p)
{
if (lstrcmpA( p, SuiteName ) == 0)
{
rVal = TRUE;
break;
}
p += (lstrlenA( p ) + 1);
}
exit:
if (ProductSuite)
LocalFree( ProductSuite );
if (hKey)
RegCloseKey( hKey );
return rVal;
}
BOOL IsTerminalServicesEnabled( VOID )
{
BOOL bResult = FALSE;
DWORD dwVersion;
OSVERSIONINFOEXA osVersionInfo;
DWORDLONG dwlConditionMask = 0;
HMODULE hmodK32 = NULL;
typedef ULONGLONG (*PFnVerSetConditionMask) ( ULONGLONG, ULONG, UCHAR );
typedef BOOL (*PFnVerifyVersionInfoA) (POSVERSIONINFOEXA, DWORD, DWORDLONG);
PFnVerSetConditionMask pfnVerSetConditionMask;
PFnVerifyVersionInfoA pfnVerifyVersionInfoA;
dwVersion = GetVersion();
/* are we running NT ? */
if (!(dwVersion & 0x80000000))
{
// Is it NT 50 or greater ?
if (LOBYTE(LOWORD(dwVersion)) > 4)
{
/* In NT5 we need to use the Product Suite APIs
Don't static link because it won't load on non-NT5 systems */
hmodK32 = GetModuleHandleA( "KERNEL32.DLL" );
if (hmodK32)
{
pfnVerSetConditionMask = (PFnVerSetConditionMask )GetProcAddress( hmodK32, "VerSetConditionMask");
if (pfnVerSetConditionMask)
{
/* get the condition mask. */
dwlConditionMask = (*pfnVerSetConditionMask)(dwlConditionMask, VER_SUITENAME, VER_AND);
pfnVerifyVersionInfoA = (PFnVerifyVersionInfoA)GetProcAddress( hmodK32, "VerifyVersionInfoA") ;
if (pfnVerifyVersionInfoA != NULL)
{
ZeroMemory(&osVersionInfo, sizeof(osVersionInfo));
osVersionInfo.dwOSVersionInfoSize = sizeof(osVersionInfo);
osVersionInfo.wSuiteMask = VER_SUITE_TERMINAL;
bResult = (*pfnVerifyVersionInfoA)(
&osVersionInfo,
VER_SUITENAME,
dwlConditionMask);
}
}
}
}
else
{
/* This is NT 40 */
bResult = ValidateProductSuite( "Terminal Server" );
}
}
return bResult;
}
/*--------------------------------------------------------------------------------------------------------
* DWORD IsStringInMultiString(HKEY hkey, LPCTSTR szkey, LPCTSTR szvalue, LPCTSTR szCheckForString, BOOL *pbFound)
* checks if parameter string exists in given multistring.
* returns error code.
* -------------------------------------------------------------------------------------------------------*/
DWORD IsStringInMultiString(HKEY hkey, LPCTSTR szkey, LPCTSTR szvalue, LPCTSTR szCheckForString, BOOL *pbFound)
{
ASSERT(szkey && *szkey);
ASSERT(szvalue && *szvalue);
ASSERT(szCheckForString&& *szCheckForString);
ASSERT(*szkey != '\\');
ASSERT(pbFound);
// not yet found.
*pbFound = FALSE;
CRegistry reg;
DWORD dwError = reg.OpenKey(hkey, szkey, KEY_READ); // open up the required key.
if (dwError == NO_ERROR)
{
LPTSTR szSuiteValue;
DWORD dwSize;
dwError = reg.ReadRegMultiString(szvalue, &szSuiteValue, &dwSize);
if (dwError == NO_ERROR)
{
LPCTSTR pTemp = szSuiteValue;
while(_tcslen(pTemp) > 0 )
{
if (_tcscmp(pTemp, szCheckForString) == 0)
{
*pbFound = TRUE;
break;
}
pTemp += _tcslen(pTemp) + 1; // point to the next string within the multistring.
if ( DWORD(pTemp - szSuiteValue) > (dwSize / sizeof(TCHAR)))
break; // temporary pointer passes the size of the szSuiteValue something is wrong with szSuiteValue.
}
}
}
return dwError;
}
BOOL DoesHydraKeysExists()
{
BOOL bStringExists = FALSE;
DWORD dw = IsStringInMultiString(
HKEY_LOCAL_MACHINE,
_T("SYSTEM\\CurrentControlSet\\Control\\ProductOptions"),
_T("ProductSuite"),
_T("Terminal Server"),
&bStringExists);
return (dw == ERROR_SUCCESS) && bStringExists;
}
TCHAR *IsItAppServer ()
{
return ((GetOSVersionInfo()->wSuiteMask & VER_SUITE_TERMINAL) &&
!(GetOSVersionInfo()->wSuiteMask & VER_SUITE_SINGLEUSERTS)) ? _T("Yes") : _T("No");
}
BOOL IsItServer ()
{
return GetOSVersionInfo()->wProductType != VER_NT_WORKSTATION;
}
TCHAR *GetProductType ()
{
BYTE wProductType = GetOSVersionInfo()->wProductType;
_tcscpy(ReturnBuffer(), _T(""));
if (wProductType == VER_NT_WORKSTATION)
{
_tcscat(ReturnBuffer(), _T("VER_NT_WORKSTATION "));
}
if (wProductType == VER_NT_DOMAIN_CONTROLLER)
{
_tcscat(ReturnBuffer(), _T("VER_NT_DOMAIN_CONTROLLER"));
}
if (wProductType == VER_NT_SERVER)
{
_tcscat(ReturnBuffer(), _T("VER_NT_SERVER"));
}
return ReturnBuffer();
}
TCHAR *GetProductSuite ()
{
WORD wProductSuite = GetOSVersionInfo()->wSuiteMask;
_tcscpy(ReturnBuffer(), _T(""));
if (wProductSuite & VER_SERVER_NT)
{
_tcscat(ReturnBuffer(), _T("VER_SERVER_NT "));
}
if (wProductSuite & VER_WORKSTATION_NT)
{
_tcscat(ReturnBuffer(), _T("VER_WORKSTATION_NT "));
}
if (wProductSuite & VER_SUITE_SMALLBUSINESS)
{
_tcscat(ReturnBuffer(), _T("VER_SUITE_SMALLBUSINESS "));
}
if (wProductSuite & VER_SUITE_ENTERPRISE)
{
_tcscat(ReturnBuffer(), _T("VER_SUITE_ENTERPRISE "));
}
if (wProductSuite & VER_SUITE_BACKOFFICE)
{
_tcscat(ReturnBuffer(), _T("VER_SUITE_BACKOFFICE "));
}
if (wProductSuite & VER_SUITE_COMMUNICATIONS)
{
_tcscat(ReturnBuffer(), _T("VER_SUITE_COMMUNICATIONS "));
}
if (wProductSuite & VER_SUITE_TERMINAL)
{
_tcscat(ReturnBuffer(), _T("VER_SUITE_TERMINAL "));
}
if (wProductSuite & VER_SUITE_SMALLBUSINESS_RESTRICTED)
{
_tcscat(ReturnBuffer(), _T("VER_SUITE_SMALLBUSINESS_RESTRICTED "));
}
if (wProductSuite & VER_SUITE_EMBEDDEDNT)
{
_tcscat(ReturnBuffer(), _T("VER_SUITE_EMBEDDEDNT "));
}
if (wProductSuite & VER_SUITE_DATACENTER)
{
_tcscat(ReturnBuffer(), _T("VER_SUITE_DATACENTER "));
}
if (wProductSuite & VER_SUITE_SINGLEUSERTS)
{
_tcscat(ReturnBuffer(), _T("VER_SUITE_SINGLEUSERTS "));
}
if (wProductSuite & VER_SUITE_PERSONAL)
{
_tcscat(ReturnBuffer(), _T("VER_SUITE_PERSONAL "));
}
return ReturnBuffer();
}
TCHAR *IsServer ()
{
return IsItServer() ? _T("Its a Server") : _T("Its a WorkStation");
}
BOOL IsKernelTSEnable ()
{
return IsTerminalServicesEnabled();
}
BOOL TSEnabled ()
{
CRegistry reg;
if ( ERROR_SUCCESS == reg.OpenKey( HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Control\\Terminal Server"), KEY_READ))
{
DWORD dwTSEnabled = 0;
if ( ERROR_SUCCESS == reg.ReadRegDWord( _T("TSEnabled"), &dwTSEnabled))
{
return dwTSEnabled == 1;
}
}
return FALSE;
}
BOOL DoesProductSuiteContainTS ()
{
return DoesHydraKeysExists ();
}
BOOL IsTerminalServerRegistryOk ()
{
CRegistry reg1;
CRegistry reg2;
CRegistry reg3;
return
(ERROR_SUCCESS == reg1.OpenKey(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Control\\Terminal Server"), KEY_READ)) &&
(ERROR_SUCCESS == reg2.OpenKey(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations"), KEY_READ)) &&
(ERROR_SUCCESS == reg3.OpenKey(HKEY_LOCAL_MACHINE, _T("Software\\Microsoft\\Windows NT\\CurrentVersion\\Terminal Server"), KEY_READ));
}
TCHAR *GetWinstationList ()
{
TCHAR szWinstationList[256];
BOOL bFoundNonConsoleWinstation = FALSE;
_tcscpy(szWinstationList, _T(""));
CRegistry reg2;
if (ERROR_SUCCESS == reg2.OpenKey(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations"), KEY_READ))
{
LPTSTR szWinstation;
DWORD dwSize;
BOOL bFirst = TRUE;
if (ERROR_SUCCESS == reg2.GetFirstSubKey(&szWinstation, &dwSize))
{
do
{
if (0 != _tcsicmp(szWinstation, _T("Console")))
{
bFoundNonConsoleWinstation = TRUE;
}
if (!bFirst)
{
_tcscat(szWinstationList, _T(", "));
}
_tcscat(szWinstationList, szWinstation);
bFirst = FALSE;
}
while (ERROR_SUCCESS == reg2.GetNextSubKey(&szWinstation, &dwSize));
}
}
if (_tcslen(szWinstationList) == 0)
{
_tcscpy(szWinstationList, _T("Error, No winstations found."));
}
if (!bFoundNonConsoleWinstation)
{
szMoreInfo << "ERROR, No non Console Winstation not found" << endl;
}
_tcscpy(ReturnBuffer(), szWinstationList);
return ReturnBuffer();
}
TCHAR *IsTerminalServiceStartBitSet ()
{
CRegistry reg;
if ( ERROR_SUCCESS == reg.OpenKey( HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\TermService"), KEY_READ))
{
DWORD dwTermServStartBit = 0;
if ( ERROR_SUCCESS == reg.ReadRegDWord( _T("Start"), &dwTermServStartBit))
{
switch (dwTermServStartBit)
{
case 2:
return _T("AutoStart");
break;
case 3:
return _T("Manual Start");
break;
case 4:
return _T("Error, Disabled");
break;
default:
return _T("ERROR:Wrong value for startbit");
}
}
}
return _T("Error, Reading startbig");
}
BOOL IsTermDDStartBitSet ()
{
CRegistry reg;
if ( ERROR_SUCCESS == reg.OpenKey( HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\TermDD"), KEY_READ))
{
DWORD dwTermDDStartBit = 0;
if ( ERROR_SUCCESS == reg.ReadRegDWord( _T("Start"), &dwTermDDStartBit))
{
return dwTermDDStartBit == 2;
}
}
return FALSE;
}
TCHAR *AreEffectiveConnectionAllowed ()
{
HMODULE hmodRegAPI = LoadLibrary( _T("RegApi.dll") );
if (hmodRegAPI)
{
typedef BOOLEAN (*PFDenyConnectionPolicy) ();
PFDenyConnectionPolicy pfnDenyConnectionPolicy;
pfnDenyConnectionPolicy = (PFDenyConnectionPolicy) GetProcAddress( hmodRegAPI, "RegDenyTSConnectionsPolicy");
if (pfnDenyConnectionPolicy)
{
return (*pfnDenyConnectionPolicy)() ? _T("Not Allowed") : _T("Allowed");
}
else
{
szMoreInfo << "Failed to get proc RegDenyTSConnectionsPolicy" << endl;
return _T("Failed");
}
}
else
{
szMoreInfo << "Failed to Load regapi.dll" << endl;
return _T("Failed");
}
}
TCHAR *AreConnectionsAllowed ()
{
DWORD dwError;
CRegistry oRegTermsrv;
dwError = oRegTermsrv.OpenKey(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Control\\Terminal Server"), KEY_READ);
if (ERROR_SUCCESS == dwError)
{
DWORD dwDenyConnect;
dwError = oRegTermsrv.ReadRegDWord(_T("fDenyTSConnections"), &dwDenyConnect);
if (ERROR_SUCCESS == dwError)
{
return dwDenyConnect ? _T("No, Not allowed") : _T("Yes");
}
}
//
// could not read registry, It means - for 51 connection not allowed. For 50 Connections allowed.
//
return IsIt51TS() ? _T("Error, Value not found") : _T("Yes");
}
BOOL GetTSOCLogFileName(char *strFileName, UINT uiSize)
{
if (!GetSystemWindowsDirectoryA(strFileName, uiSize))
return FALSE;
strcat(strFileName, "\\tsoc.log");
ASSERT(strlen(strFileName) < uiSize);
return TRUE;
}
char *IncompleteMessage = "Error:TSOC Did not get OC_COMPLETE_INSTALLATION.";
BOOL DidTsOCgetCompleteInstallationMessage ()
{
if (!IsTSOClogPresent())
{
szMoreInfo << "tsoc.log does not exist." << endl;
return FALSE;
}
char strTSOCLog[256];
GetTSOCLogFileName(strTSOCLog, 256);
ifstream ifSrc(strTSOCLog);
if(!ifSrc)
{
szMoreInfo << "Failed to open tsoc.log file." << endl;
return FALSE;
}
char tempSrc[256];
while(!ifSrc.eof())
{
ifSrc.getline(tempSrc, 256);
if (strstr(tempSrc, IncompleteMessage))
{
return FALSE;
}
}
return TRUE;
}
BOOL FileExists(char *pszFullNameAndPath)
{
ASSERT(pszFullNameAndPath);
if (pszFullNameAndPath && pszFullNameAndPath[0])
{
HANDLE hFile = CreateFileA(pszFullNameAndPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
CloseHandle(hFile);
return TRUE;
}
}
return FALSE;
}
BOOL IsTSOClogPresent ()
{
char strTSOCLog[256];
GetTSOCLogFileName(strTSOCLog, 256);
return FileExists(strTSOCLog);
}
BOOL DidOCMInstallTSEnable()
{
CRegistry reg;
if ( ERROR_SUCCESS == reg.OpenKey( HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\OC Manager\\SubComponents"), KEY_READ))
{
DWORD dwTSEnabled = 0;
if ( ERROR_SUCCESS == reg.ReadRegDWord( _T("tsenable"), &dwTSEnabled))
{
return dwTSEnabled == 1;
}
}
return FALSE;
}
TCHAR *IsClusteringInstalled ()
{
DWORD dwClusterState;
if (ERROR_SUCCESS == GetNodeClusterState(NULL, &dwClusterState))
{
if (dwClusterState != ClusterStateNotInstalled)
{
return _T("***Failed. Clustering is installed, this is not compatible with Terminal Server.");
}
}
return _T("Passed");
}
TCHAR *GetTSMode (void)
{
return IsRemoteAdminMode() ? _T("Remote Admin") : _T("Application Server");
}
BOOL IsRemoteAdminMode ()
{
// HKLM ,"SYSTEM\CurrentControlSet\Control\Terminal Server","TSAppCompat",0x00010001,0x0
CRegistry reg;
if ( ERROR_SUCCESS == reg.OpenKey( HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Control\\Terminal Server"), KEY_READ))
{
DWORD dwAppCompat = 1;
if ( ERROR_SUCCESS == reg.ReadRegDWord( _T("TSAppCompat"), &dwAppCompat))
{
return dwAppCompat == 0;
}
else
{
// if the registry TSAppCompat does not exist it means we are in app server mode.
return FALSE;
}
}
else
{
szMoreInfo << "ERROR:SYSTEM\\CurrentControlSet\\Control\\Terminal Server not found!" << endl;
}
// this return is bogus.
return TRUE;
}
BOOL VerifyModeRegistry()
{
return CheckModeRegistry(!IsRemoteAdminMode());
}
BOOL CheckModeRegistry (BOOL bAppCompat)
{
USES_CONVERSION;
BOOL bOk = TRUE;
CRegistry reg;
if (IsItServer())
{
CRegistry reg1;
// check registry value
// for appcompat mode
//HKLM ,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon","AppSetup",0x00000000,"UsrLogon.Cmd"
// and for remote admin mode
//HKLM ,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon","AppSetup",0x00000000,""
if ( ERROR_SUCCESS == reg1.OpenKey( HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"), KEY_READ))
{
LPTSTR str;
DWORD dwSize;
if (ERROR_SUCCESS == reg1.ReadRegString(_T("AppSetup"), &str, &dwSize))
{
if (bAppCompat)
{
if (_tcsicmp(str, _T("UsrLogon.Cmd")) != 0)
{
bOk = FALSE;
szMoreInfo << "ERROR: Wrong value (" << T2A(str) << ") for AppSetup, contact makarp/breenh" << endl;
}
}
else
{
if (_tcslen(str) != 0)
{
bOk = FALSE;
szMoreInfo << "ERROR: Wrong value (" << T2A(str) << ") for AppSetup, contact makarp/breenh" << endl;
}
}
}
else
{
szMoreInfo << "ERROR reading appsetup registry" << endl;
bOk = FALSE;
}
}
else
{
szMoreInfo << "ERROR:reading SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon" << endl;
bOk = FALSE;
}
}
// check registry value
// for appcompat mode
//HKLM ,"SYSTEM\CurrentControlSet\Control\PriorityControl","Win32PrioritySeparation", 0x00010001,0x26
// and for remote admin mode
//HKLM ,"SYSTEM\CurrentControlSet\Control\PriorityControl","Win32PrioritySeparation", 0x00010001,0x18
if ( ERROR_SUCCESS == reg.OpenKey( HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Control\\PriorityControl"), KEY_READ))
{
DWORD dwPriority;
if (ERROR_SUCCESS == reg.ReadRegDWord(_T("Win32PrioritySeparation"), &dwPriority))
{
if (bAppCompat)
{
if (0x26 != dwPriority)
{
bOk = FALSE;
szMoreInfo << "ERROR: Wrong Win32PrioritySeparation (" << dwPriority << ")" << endl;
}
}
else if (IsItServer())
{
if (0x18 != dwPriority)
{
bOk = FALSE;
szMoreInfo << "ERROR: Wrong Win32PrioritySeparation (" << dwPriority << ")" << endl;
}
}
}
else
{
bOk = FALSE;
szMoreInfo << "ERROR:Reading Win32PrioritySeparation registry" << endl;
}
}
else
{
bOk = FALSE;
szMoreInfo << "ERROR:Reading PriorityControl registry" << endl;
}
// check registry value
// for appcompat mode
//HKLM ,"SYSTEM\CurrentControlSet\Control\Terminal Server","IdleWinStationPoolCount",0x00010001,0x2
// and for remote admin mode
//HKLM ,"SYSTEM\CurrentControlSet\Control\Terminal Server","IdleWinStationPoolCount",0x00010001,0x0
if ( ERROR_SUCCESS == reg.OpenKey( HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Control\\Terminal Server"), KEY_READ))
{
DWORD dwIdleWinstations;
if (ERROR_SUCCESS == reg.ReadRegDWord(_T("IdleWinStationPoolCount"), &dwIdleWinstations))
{
if (bAppCompat)
{
if (0x2 != dwIdleWinstations)
{
bOk = FALSE;
szMoreInfo << "ERROR: Wrong IdleWinStationPoolCount (" << dwIdleWinstations << ")" << endl;
}
}
else
{
if (0 != dwIdleWinstations)
{
bOk = FALSE;
szMoreInfo << "ERROR: Wrong IdleWinStationPoolCount (" << dwIdleWinstations << ")" << endl;
}
}
}
else
{
bOk = FALSE;
szMoreInfo << "ERROR:Reading IdleWinStationPoolCount registry" << endl;
}
}
else
{
bOk = FALSE;
szMoreInfo << "SYSTEM\\CurrentControlSet\\Control\\Terminal Server" << endl;
}
return bOk;
}
BOOL IsTerminalServiceRunning ()
{
BOOL bReturn = FALSE;
SC_HANDLE hServiceController = OpenSCManager(NULL, NULL, GENERIC_READ);
if (hServiceController)
{
SC_HANDLE hTermServ = OpenService(hServiceController, _T("TermService"), SERVICE_QUERY_STATUS);
if (hTermServ)
{
SERVICE_STATUS tTermServStatus;
if (QueryServiceStatus(hTermServ, &tTermServStatus))
{
bReturn = (tTermServStatus.dwCurrentState == SERVICE_RUNNING);
}
else
{
szMoreInfo << "Failed to get service status, Error = " << GetLastError() << endl;
}
VERIFY(CloseServiceHandle(hTermServ));
}
else
{
szMoreInfo << "Failed to open TermServ service, Error = " << GetLastError() << endl;
}
VERIFY(CloseServiceHandle(hServiceController));
}
else
{
szMoreInfo << "Failed to Open Service Controller, Error = " << GetLastError() << endl;
}
return bReturn;
}
BOOL CheckVideoKeys ()
{
// HKLM ,"SYSTEM\CurrentControlSet\Control\Terminal Server\VIDEO\rdpdd","VgaCompatible",0x00000000,"\Device\Video0"
// HKLM ,"SYSTEM\CurrentControlSet\Control\Terminal Server\VIDEO\rdpdd","\Device\Video0",0x00000000,"\REGISTRY\Machine\System\ControlSet001\Services\RDPDD\Device0"
CRegistry reg;
if ( ERROR_SUCCESS == reg.OpenKey( HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\VIDEO\\rdpdd"), KEY_READ))
{
LPTSTR str = 0;
DWORD dwSize = 0;
if (ERROR_SUCCESS == reg.ReadRegString(_T("VgaCompatible"), &str, &dwSize))
{
if (0 == _tcsicmp(str, _T("\\Device\\Video0")))
{
if (ERROR_SUCCESS == reg.ReadRegString(_T("\\Device\\Video0"), &str, &dwSize))
{
if ((0 == _tcsicmp(str, _T("\\REGISTRY\\Machine\\System\\ControlSet001\\Services\\RDPDD\\Device0"))) ||
(0 == _tcsicmp(str, _T("\\REGISTRY\\Machine\\System\\CurrentControlSet\\Services\\RDPDD\\Device0"))))
{
return TRUE;
}
else
{
}
}
else
{
}
}
else
{
}
}
else
{
}
}
else
{
}
return FALSE;
}
TCHAR szCompName[256];
TCHAR *GetCompName ()
{
DWORD dwCompName = 256;
if (GetComputerName(szCompName, &dwCompName))
{
return szCompName;
}
return NULL;
}
TCHAR szDomNameWorkgroup[] = _T("<Workgroup>");
TCHAR szDomNameUnknown[] = _T("<Unknown>");
TCHAR *GetDomName ()
{
DSROLE_PRIMARY_DOMAIN_INFO_BASIC *pDomainInfo = NULL;
DWORD dwErr;
//
// Check if we're in a workgroup
//
dwErr = DsRoleGetPrimaryDomainInformation(NULL,
DsRolePrimaryDomainInfoBasic,
(PBYTE *) &pDomainInfo);
if (ERROR_SUCCESS != dwErr)
return szDomNameUnknown;
switch (pDomainInfo->MachineRole)
{
case DsRole_RoleStandaloneWorkstation:
case DsRole_RoleStandaloneServer:
return szDomNameWorkgroup;
break; // just in case
}
if (pDomainInfo->DomainNameFlat)
return pDomainInfo->DomainNameFlat;
else if (pDomainInfo->DomainNameDns)
return pDomainInfo->DomainNameDns;
else
return szDomNameUnknown;
}
WCHAR wszIPAddress[128] = L"<error>";
TCHAR *GetIPAddress ()
{
//get host address
WORD wVersionRequested = MAKEWORD( 1, 1 );
WSADATA wsaData;
if (0 == WSAStartup(wVersionRequested,&wsaData))
{
char szHostName[256];
if (0 == gethostname ( szHostName , 256 ))
{
hostent *h;
if (NULL != (h=gethostbyname ( szHostName )))
{
in_addr *inaddr=(struct in_addr *)*h->h_addr_list;
MultiByteToWideChar(CP_ACP,0,inet_ntoa(*inaddr),-1,wszIPAddress,128);
}
}
}
return wszIPAddress;
}
TCHAR *IsRDPNPinNetProviders ()
{
TCHAR NEWORK_PROVIDER_ORDER_KEY[] = _T("SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order");
TCHAR PROVIDER_ORDER_VALUE[] = _T("ProviderOrder");
TCHAR RDPNP_ENTRY[] = _T("RDPNP");
BOOL bRdpNpExists = FALSE;
// read network privider key.
CRegistry regNetOrder;
LPTSTR szOldValue;
DWORD dwSize;
if ((ERROR_SUCCESS == regNetOrder.OpenKey(HKEY_LOCAL_MACHINE, NEWORK_PROVIDER_ORDER_KEY), KEY_READ) &&
(ERROR_SUCCESS == regNetOrder.ReadRegString(PROVIDER_ORDER_VALUE, &szOldValue, &dwSize)))
{
bRdpNpExists = (_tcsstr(szOldValue, RDPNP_ENTRY) != NULL);
}
if (TSEnabled () == bRdpNpExists)
{
return (_T("Passed"));
}
else
{
if (bRdpNpExists)
{
return _T("Error: RDPNP, exists in ProviderOrder, but TS is disabled!");
}
else
{
if (IsIt50TS())
{
// rdp np is only for 51+ so its ok if its missing for 50.
return _T("Passed");
}
else
{
return _T("ERROR, RDPNP is missing from ProviderOrder");
}
}
}
}
TCHAR *IsMultiConnectionAllowed ()
{
// SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon","AllowMultipleTSSessions
CRegistry regWL;
DWORD dwAllowMultipal;
if ((ERROR_SUCCESS == regWL.OpenKey(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"), KEY_READ)) &&
(ERROR_SUCCESS == regWL.ReadRegDWord(_T("AllowMultipleTSSessions"), &dwAllowMultipal)))
{
return dwAllowMultipal ? _T("Yes") : _T("No");
}
if (IsIt50TS())
{
return _T("Yes");
}
else
{
return _T("ERROR, registry missing");
}
}
TCHAR *LogonType ()
{
if (0 == _tcsicmp(GetDomName(), szDomNameWorkgroup))
{
CRegistry regWL;
DWORD dwLogonType;
if ((ERROR_SUCCESS == regWL.OpenKey(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"), KEY_READ)) &&
(ERROR_SUCCESS == regWL.ReadRegDWord(_T("LogonType"), &dwLogonType)))
{
return dwLogonType == 0 ? _T("Classic Gina") : _T("New Fancy");
}
if (IsIt50TS())
{
return _T("Classic");
}
else
{
return _T("ERROR, registry missing");
}
}
else
{
return _T("Classic Gina");
}
}
BOOL IsTermSrvInSystemContext ()
{
USES_CONVERSION;
CRegistry reg;
if ( ERROR_SUCCESS == reg.OpenKey( HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\TermService"), KEY_READ))
{
TCHAR *szObjectName;
DWORD dwSize;
if ( ERROR_SUCCESS == reg.ReadRegString( _T("ObjectName"), &szObjectName, &dwSize))
{
if (0 == _tcsicmp(szObjectName, _T("LocalSystem")))
{
return TRUE;
}
else
{
szMoreInfo << "ERROR:Termsrv is set to run using (" << T2A(szObjectName) << ") context." << endl;
}
}
else
{
szMoreInfo << "failed to read Objectname" << endl;
}
}
else
{
szMoreInfo << "failed to open termsrv registry" << endl;
}
return FALSE;
}
BOOL DontRun ()
{
szMoreInfo << "test not run because its not required." << endl;
return FALSE;
}
BOOL DoRun ()
{
szMoreInfo << "this test must be run." << endl;
return TRUE;
}
TCHAR *SystemDirectory()
{
TCHAR sysdir[MAX_PATH];
sysdir[0] = '\0';
if (GetSystemDirectory(sysdir, MAX_PATH) >= MAX_PATH) {
sysdir[MAX_PATH -1] = '\0';
}
_tcscpy(ReturnBuffer(), sysdir);
return ReturnBuffer();
}
int
#if !defined(_MIPS_) && !defined(_ALPHA_) && !defined(_PPC_)
_cdecl
#endif
main( int argc , char ** /* argv */)
{
typedef BOOL (PFN_BOOL)(void);
typedef TCHAR * (PFN_TestSubjective)(void);
USES_CONVERSION;
struct TVerificationTest
{
char szTestName[256]; // descriptive name of the test
PFN_BOOL *pfnNeedRunTest; // pointer to function that will be called to decide if the test need run, test is run if NULL.
PFN_TestSubjective *pfnSubTest; // pointer to function if the test returns TCHAR *
PFN_BOOL *pfnObjTest; // pointer to function if the test returns BOOL
}
theTests[] =
{
// {"DontRun...............................", DontRun, GetCompName, NULL},
// {"DoRun...............................", DoRun, GetCompName, NULL},
{"Machine Name...............................", NULL, GetCompName, NULL},
{"Domain Name................................", NULL, GetDomName, NULL},
{"IP Address.................................", NULL, GetIPAddress, NULL},
{"System Dir.................................", NULL, SystemDirectory, NULL},
{"ProductType................................", NULL, GetProductType, NULL},
{"ProductSuite...............................", NULL, GetProductSuite, NULL},
{"TS Version.................................", NULL, GetTSVersion, NULL},
{"Is this a server machine?..................", NULL, IsServer, NULL},
{"Is tsoc.log Present?.......................", NULL, NULL, IsTSOClogPresent},
{"Did TsOC get CompleteInstallationMessage...", NULL, NULL, DidTsOCgetCompleteInstallationMessage},
{"Is Clustering Services installed...........", NULL, IsClusteringInstalled, NULL},
{"Does ProductSuite Contain TS?..............", NULL, NULL, DoesProductSuiteContainTS},
{"Did OCM Install TSEnable...................", IsIt50TS, NULL, DidOCMInstallTSEnable},
{"Is TSEnabled registry alright?.............", NULL, NULL, TSEnabled},
{"Is Kernel TSEnabled?.......................", IsItServer, NULL, IsKernelTSEnable},
{"Is Terminal Server Registry Ok?............", NULL, NULL, IsTerminalServerRegistryOk},
{"GetWinstationList..........................", NULL, GetWinstationList, NULL},
{"Is TermServ Start Bit Ok?..................", NULL, IsTerminalServiceStartBitSet, NULL},
{"Is TermServ service running?...............", NULL, NULL, IsTerminalServiceRunning},
{"Is TermSrv in System Context?..............", NULL, NULL, IsTermSrvInSystemContext},
{"AreEffectiveConnectionAllowed..............", IsIt51TS, AreEffectiveConnectionAllowed, NULL },
{"Are Connections Allowed?...................", IsIt51TS, AreConnectionsAllowed, NULL},
{"Is RdpDr Installed Properly?...............", NULL, NULL, IsRdpDrInstalledProperly},
{"Is RdpNP in NetProviders?..................", IsIt51TS, IsRDPNPinNetProviders, NULL},
{"Are Multipal Connections Allowed...........", IsIt51TS, IsMultiConnectionAllowed, NULL},
{"Logon UI type..............................", IsIt51TS, LogonType, NULL},
{"Are Video keys setup right?................", NULL, NULL, CheckVideoKeys},
{"What mode is Terminal Server set in?.......", NULL, GetTSMode, NULL},
{"Is mode specific registry ok?..............", NULL, NULL, VerifyModeRegistry},
{"What is permission Mode set to?............", NULL, GetModePermissions, NULL},
{"Check termdd signature.....................", NULL, NULL, Check_termdd},
{"Check tdpipe signature.....................", NULL, NULL, Check_tdpipe},
{"Check tdtcp signature......................", NULL, NULL, Check_tdtcp},
{"Check rdpwd signature......................", NULL, NULL, Check_rdpwd},
{"Check rdpdd signature......................", NULL, NULL, Check_rdpdd},
{"Check rdpwsx signature.....................", NULL, NULL, Check_rdpwsx},
{"Is it 56 bit or 128?.......................", NULL, GetCypherStrenthOnRdpwd, NULL},
{"Is this a Beta System?.....................", NULL, IsBetaSystem, NULL},
{"Has Licence GracePeriod Expired............", NULL, IsLicenceGracePeriodOk, NULL},
{"Audio test.................................", IsIt51TS, NULL, IsAudioOk}
};
BOOL bEverythingOk = TRUE;
for (int i=0; i < sizeof(theTests)/sizeof(theTests[0]); i++)
{
ASSERT(theTests[i].pfnObjTest || theTests[i].pfnSubTest);
ASSERT(!(theTests[i].pfnObjTest && theTests[i].pfnSubTest));
if (theTests[i].pfnNeedRunTest && !(*(theTests[i].pfnNeedRunTest))())
{
// we asre asked to skip the test.
cout << theTests[i].szTestName << "Skipped Test" << endl;
}
else
{
if (theTests[i].pfnObjTest)
{
BOOL bResult = (*(theTests[i].pfnObjTest))();
cout << theTests[i].szTestName << (bResult ? "Passed" : "Failed") << endl;
if (!bResult)
bEverythingOk = FALSE;
}
else
{
char *szStr = T2A((*(theTests[i].pfnSubTest))());
if (szStr)
{
cout << theTests[i].szTestName << szStr << endl;
}
}
}
//
// if previous test had any details to tell us
//
if (szMoreInfo.pcount())
{
char *pStr = szMoreInfo.str();
cout << " Details:" << pStr;
cout << "------------------------------------------------" << endl;
bEverythingOk = FALSE;
ZeroMemory(pStr, 512);
szMoreInfo.seekp(ios::beg);
}
}
cout << endl;
if (argc == 1 ) // if some argumnent is provided skip these time consuming test.
{
cout << "Enumerating Licensing Servers (May take some time)...";
cout.flush();
if (EnumerateLicenseServers())
{
cout << ".....Passed, Found Some!" << endl;
}
else
{
cout << ".....Failed. No License Server Found." << endl;
}
cout << "Extracting Related Events from Event Log...";
cout.flush();
if (ExtractAllTSEvents())
{
cout << ".....Found Some. See if they give any clue." << endl;
}
else
{
cout << ".....Found None." << endl;
}
}
cout << endl;
if (bEverythingOk)
{
cout << endl;
cout << "**************************************************************" << endl;
cout << "*** Nothing wrong with TS could detected by this utility. ***" << endl;
cout << "*** If you think something is wrong contact the developer. ***" << endl;
cout << "**************************************************************" << endl;
return 0;
}
return 1;
}