2790 lines
65 KiB
C++
2790 lines
65 KiB
C++
// Copyright (c) 1998 - 1999 Microsoft Corporation
|
|
|
|
|
|
|
|
#include "nt.h"
|
|
#include "ntrtl.h"
|
|
#include "nturtl.h"
|
|
#include "stdafx.h"
|
|
#include <dsrole.h>
|
|
#include <wtsapi32.h>
|
|
#include "winsta.h"
|
|
#include "tstst.h"
|
|
#include "testdata.h"
|
|
#include <rdpsndp.h>
|
|
#include <rdpstrm.h>
|
|
//
|
|
// global utilities and veraibles.
|
|
//
|
|
bool CheckifBinaryisSigned (TCHAR *szFile); // from tscert.cpp
|
|
bool EnumerateLicenseServers (); // from timebomb.cpp
|
|
bool HasLicenceGracePeriodExpired (); // from timebomb.cpp
|
|
bool ExtractAllTSEvents();
|
|
TCHAR *GetLicenseServers ();
|
|
bool ValidateProductSuite (LPSTR SuiteName);
|
|
bool IsTerminalServicesEnabled ( VOID );
|
|
DWORD IsStringInMultiString(HKEY hkey, LPCTSTR szkey, LPCTSTR szvalue, LPCTSTR szCheckForString, bool *pbFound);
|
|
bool DoesHydraKeysExists ();
|
|
bool IsItRemoteMachine ();
|
|
|
|
|
|
bool IsTermDDStartBitSet ();
|
|
bool GetTSOCLogFileName (char *strFileName, UINT uiSize);
|
|
bool FileExists (char *pszFullNameAndPath);
|
|
bool IsRemoteAdminMode ();
|
|
bool CheckModePermissions(DWORD *pdwSecurtyMode);
|
|
bool IsFile128Bit(LPTSTR szFile, bool *pb128Bit);
|
|
ULONG RDPDRINST_DetectInstall(); // defined in drdetect.cpp
|
|
bool IsBetaSystem();
|
|
bool CheckModeRegistry (bool bAppCompat, ostrstream &ResultStream);
|
|
bool GetWinstationConfiguration (WINSTATIONCONFIG **ppInfo);
|
|
|
|
bool CanPing (); // comes from ping.cpp
|
|
|
|
const SERVER_INFO_101 *GetServerInfo()
|
|
{
|
|
ASSERT(IsItRemoteMachine());
|
|
|
|
// for local machines, we will get GetMachineName() as null,
|
|
if (CTSTestData::GetMachineName())
|
|
{
|
|
USES_CONVERSION;
|
|
static SERVER_INFO_101 ServerInfo;
|
|
LPBYTE Buffer;
|
|
static bool bGotOnce = false;
|
|
if (!bGotOnce)
|
|
{
|
|
TCHAR szMachineName[256];
|
|
_tcscpy(szMachineName, CTSTestData::GetMachineName());
|
|
if (NERR_Success == NetServerGetInfo(
|
|
T2W(szMachineName),
|
|
102,
|
|
&Buffer
|
|
))
|
|
{
|
|
bGotOnce = true;
|
|
CopyMemory(&ServerInfo, Buffer, sizeof(SERVER_INFO_101));
|
|
return &ServerInfo;
|
|
}
|
|
else
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return &ServerInfo;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
const OSVERSIONINFOEX *GetOSVersionInfo()
|
|
{
|
|
ASSERT(!IsItRemoteMachine());
|
|
static OSVERSIONINFOEX gOsVersion;
|
|
static bool 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_)))
|
|
|
|
|
|
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 *GetTSVersion()
|
|
{
|
|
static TCHAR Version[256] = TEXT("");
|
|
|
|
if (_tcslen(Version) != 0)
|
|
return Version;
|
|
|
|
CRegistry oRegTermsrv;
|
|
DWORD cbVersion = 0;
|
|
LPTSTR szVersion = NULL;
|
|
|
|
if ((ERROR_SUCCESS == oRegTermsrv.OpenKey(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Control\\Terminal Server"), KEY_READ, CTSTestData::GetMachineName())) &&
|
|
(ERROR_SUCCESS == oRegTermsrv.ReadRegString(_T("ProductVersion"), &szVersion, &cbVersion)))
|
|
{
|
|
_tcscpy(Version, szVersion);
|
|
return Version;
|
|
}
|
|
|
|
return _T("Error finding Version.");
|
|
}
|
|
|
|
EResult GetTSVersion (ostrstream &ResultStream)
|
|
{
|
|
USES_CONVERSION;
|
|
ResultStream << T2A(GetTSVersion());
|
|
return ePassed;
|
|
}
|
|
|
|
bool IsIt50TS()
|
|
{
|
|
return (0 == _tcsicmp(GetTSVersion(), _T("5.0")));
|
|
}
|
|
|
|
bool IsIt51TS()
|
|
{
|
|
return (0 == _tcsicmp(GetTSVersion(), _T("5.1")));
|
|
}
|
|
|
|
|
|
bool DoIhaveRPCPermissions ()
|
|
{
|
|
HANDLE hServer = WTS_CURRENT_SERVER_HANDLE;
|
|
if (CTSTestData::GetMachineName())
|
|
{
|
|
TCHAR szMachineName[256];
|
|
_tcscpy(szMachineName, CTSTestData::GetMachineName());
|
|
hServer = WTSOpenServer (szMachineName);
|
|
}
|
|
|
|
LPTSTR buffer;
|
|
DWORD dwBytesReturned;
|
|
if (WTSQuerySessionInformation(
|
|
hServer,
|
|
65536,
|
|
WTSInitialProgram,
|
|
&buffer,
|
|
&dwBytesReturned))
|
|
{
|
|
WTSFreeMemory(buffer);
|
|
return true;
|
|
}
|
|
|
|
if (CTSTestData::GetMachineName())
|
|
WTSCloseServer(hServer);
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
bool DoIHaveEnufPermissions ()
|
|
{
|
|
char szOutput[512];
|
|
ostrstream oTestResult(szOutput, 512);
|
|
ZeroMemory(oTestResult.str(), 512);
|
|
|
|
|
|
if (!DoIhaveRPCPermissions())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
CRegistry oRegTermsrv;
|
|
return ERROR_SUCCESS == oRegTermsrv.OpenKey(
|
|
HKEY_LOCAL_MACHINE,
|
|
_T("SYSTEM\\CurrentControlSet\\Control\\Terminal Server"),
|
|
KEY_READ,
|
|
CTSTestData::GetMachineName()
|
|
);
|
|
}
|
|
|
|
bool IsUserRemoteAdmin ()
|
|
{
|
|
if (IsItRemoteMachine())
|
|
{
|
|
USES_CONVERSION;
|
|
TCHAR strNTFilename[256];
|
|
if (CTSTestData::GetMachineNamePath())
|
|
{
|
|
_tcscpy(strNTFilename, CTSTestData::GetMachineNamePath());
|
|
_tcscat(strNTFilename, _T("\\admin$\\system32\\ntoskrnl.exe"));
|
|
}
|
|
|
|
HANDLE hFile = CreateFile(strNTFilename, 0, FILE_SHARE_READ,
|
|
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
if (hFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseHandle(hFile);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
// we dont require admin priviledges if running on local machine
|
|
return true;
|
|
}
|
|
}
|
|
|
|
EResult HasLicenceGracePeriodExpired (ostrstream &ResultStream)
|
|
{
|
|
if (HasLicenceGracePeriodExpired())
|
|
{
|
|
ResultStream << "Its expired";
|
|
return eFailed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "No, its not expired.";
|
|
return ePassed;
|
|
}
|
|
}
|
|
|
|
EResult Check_StackBinSigatures (ostrstream &ResultStream)
|
|
{
|
|
|
|
USES_CONVERSION;
|
|
bool bRet = true;
|
|
|
|
LPTSTR aStackBins[] =
|
|
{
|
|
_T("%SystemRoot%\\system32\\drivers\\termdd.sys"),
|
|
_T("%SystemRoot%\\system32\\drivers\\tdpipe.sys"),
|
|
_T("%SystemRoot%\\system32\\drivers\\tdtcp.sys"),
|
|
_T("%SystemRoot%\\system32\\drivers\\rdpwd.sys"),
|
|
_T("%SystemRoot%\\system32\\rdpdd.dll"),
|
|
_T("%SystemRoot%\\system32\\rdpwsx.dll")
|
|
};
|
|
|
|
for (int i = 0; i < sizeof(aStackBins)/sizeof(aStackBins[0]); i++)
|
|
{
|
|
if (!CheckifBinaryisSigned(aStackBins[i]))
|
|
{
|
|
ResultStream << "Invalid Signature for:" << T2A(aStackBins[i]) << ",";
|
|
bRet = false;
|
|
}
|
|
|
|
}
|
|
|
|
if (bRet)
|
|
{
|
|
ResultStream << "Passed";
|
|
return ePassed;
|
|
}
|
|
else
|
|
{
|
|
return eFailed;
|
|
}
|
|
}
|
|
|
|
EResult IsRdpDrInstalledProperly (ostrstream &ResultStream)
|
|
{
|
|
//
|
|
// we cannot do this test for remote machine.
|
|
//
|
|
ASSERT(IsItLocalMachine());
|
|
if (RDPDRINST_DetectInstall())
|
|
{
|
|
ResultStream << "Passed";
|
|
return ePassed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed";
|
|
return eFailed;
|
|
|
|
}
|
|
}
|
|
|
|
EResult GetModePermissions (ostrstream &ResultStream)
|
|
{
|
|
CRegistry reg;
|
|
DWORD dwSecurityMode;
|
|
if ( ERROR_SUCCESS == reg.OpenKey( HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Control\\Terminal Server"), KEY_READ, CTSTestData::GetMachineName()))
|
|
{
|
|
if ( ERROR_SUCCESS == reg.ReadRegDWord( _T("TSUserEnabled"), &dwSecurityMode))
|
|
{
|
|
if (dwSecurityMode == 0)
|
|
{
|
|
ResultStream << "Its W2k Compatible";
|
|
return ePassed;
|
|
}
|
|
else if (dwSecurityMode == 1)
|
|
{
|
|
ResultStream << "Its TS4 Compatible";
|
|
return ePassed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "SYSTEM\\CurrentControlSet\\Control\\Terminal Server/TSUserEnabled has wrong value" << dwSecurityMode << "!";
|
|
return eFailedToExecute;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "failed to read TSUserEnabled";
|
|
return eFailedToExecute;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "failed to read SYSTEM\\CurrentControlSet\\Control\\Terminal Server";
|
|
return eFailedToExecute;
|
|
}
|
|
|
|
}
|
|
|
|
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, CTSTestData::GetMachineName()))
|
|
{
|
|
if ( ERROR_SUCCESS == reg.ReadRegDWord( _T("TSUserEnabled"), pdwSecurtyMode))
|
|
{
|
|
return (*pdwSecurtyMode== 0) || (*pdwSecurtyMode== 1);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
EResult GetCypherStrenthOnRdpwd (ostrstream &ResultStream)
|
|
{
|
|
|
|
bool bFile128bit;
|
|
TCHAR strFileName[256];
|
|
|
|
if (CTSTestData::GetMachineName())
|
|
{
|
|
_tcscpy(strFileName, CTSTestData::GetMachineNamePath());
|
|
_tcscat(strFileName, _T("\\admin$\\system32\\drivers\\rdpwd.sys"));
|
|
}
|
|
else
|
|
{
|
|
_tcscpy(strFileName, _T("%SystemRoot%\\system32\\drivers\\rdpwd.sys"));
|
|
}
|
|
|
|
if ( IsFile128Bit(strFileName, &bFile128bit) )
|
|
{
|
|
ResultStream << (bFile128bit ? "128 Bit" : "56 Bit");
|
|
return ePassed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed to get cypher strength on rdpwd.sys, You may not have sufficient permissions.";
|
|
return eFailedToExecute;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
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) != 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
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, CTSTestData::GetMachineName()); // 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 IsItPTS( VOID )
|
|
{
|
|
return ( 0 != (GetOSVersionInfo()->wSuiteMask & VER_SUITE_SINGLEUSERTS));
|
|
}
|
|
|
|
bool IsItRemoteMachine ()
|
|
{
|
|
return CTSTestData::GetMachineName() != NULL;
|
|
}
|
|
|
|
bool AreWeInsideSession ()
|
|
{
|
|
return GetSystemMetrics(SM_REMOTESESSION) != 0;
|
|
}
|
|
|
|
bool IsItLocalMachine ()
|
|
{
|
|
return !IsItRemoteMachine ();
|
|
}
|
|
|
|
bool IsItLocalServer ()
|
|
{
|
|
return IsItServer () && IsItLocalMachine ();
|
|
}
|
|
|
|
bool IsItServer ()
|
|
{
|
|
if (IsItRemoteMachine())
|
|
{
|
|
const SERVER_INFO_101 *pServerInfo;
|
|
pServerInfo = GetServerInfo();
|
|
if (pServerInfo)
|
|
{
|
|
return ( (pServerInfo->sv101_type & SV_TYPE_DOMAIN_CTRL) ||
|
|
(pServerInfo->sv101_type & SV_TYPE_DOMAIN_BAKCTRL) ||
|
|
(pServerInfo->sv101_type & SV_TYPE_SERVER_NT));
|
|
}
|
|
else
|
|
{
|
|
|
|
return true; // we could not determine if its server or not, Lets say its server.
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
return GetOSVersionInfo()->wProductType != VER_NT_WORKSTATION;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
bool IsAudioEnabled()
|
|
{
|
|
USES_CONVERSION;
|
|
WINSTATIONCONFIG *pWSInfo = NULL;
|
|
|
|
if ( !AreWeInsideSession() )
|
|
return FALSE;
|
|
|
|
if (GetWinstationConfiguration(&pWSInfo))
|
|
{
|
|
return !(pWSInfo->User.fDisableCam);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
bool IsItRemoteConsole( VOID )
|
|
{
|
|
return ( AreWeInsideSession() && (NtCurrentPeb()->SessionId == 0 || IsItPTS()) );
|
|
}
|
|
|
|
EResult IsItServer (ostrstream &ResultStream)
|
|
{
|
|
ResultStream << (IsItServer ()) ? "Its a workstation" : "Its a server";
|
|
return (IsItServer()) ? ePassed : eFailed;
|
|
}
|
|
|
|
EResult GetProductType (ostrstream &ResultStream)
|
|
{
|
|
ASSERT(IsItLocalMachine());
|
|
BYTE wProductType = GetOSVersionInfo()->wProductType;
|
|
if (wProductType == VER_NT_WORKSTATION)
|
|
{
|
|
ResultStream << "VER_NT_WORKSTATION";
|
|
}
|
|
|
|
if (wProductType == VER_NT_DOMAIN_CONTROLLER)
|
|
{
|
|
ResultStream << "VER_NT_DOMAIN_CONTROLLER ";
|
|
}
|
|
|
|
if (wProductType == VER_NT_SERVER)
|
|
{
|
|
ResultStream << "VER_NT_SERVER ";
|
|
}
|
|
|
|
return ePassed;
|
|
}
|
|
|
|
|
|
EResult GetProductSuite (ostrstream &ResultStream)
|
|
{
|
|
ASSERT(IsItLocalMachine());
|
|
WORD wProductSuite = GetOSVersionInfo()->wSuiteMask;
|
|
|
|
if (wProductSuite & VER_SERVER_NT)
|
|
{
|
|
ResultStream << "VER_SERVER_NT ";
|
|
}
|
|
if (wProductSuite & VER_WORKSTATION_NT)
|
|
{
|
|
ResultStream << "VER_WORKSTATION_NT ";
|
|
}
|
|
if (wProductSuite & VER_SUITE_SMALLBUSINESS)
|
|
{
|
|
ResultStream << "VER_SUITE_SMALLBUSINESS ";
|
|
}
|
|
if (wProductSuite & VER_SUITE_ENTERPRISE)
|
|
{
|
|
ResultStream << "VER_SUITE_ENTERPRISE ";
|
|
}
|
|
if (wProductSuite & VER_SUITE_BACKOFFICE)
|
|
{
|
|
ResultStream << "VER_SUITE_BACKOFFICE ";
|
|
}
|
|
if (wProductSuite & VER_SUITE_COMMUNICATIONS)
|
|
{
|
|
ResultStream << "VER_SUITE_COMMUNICATIONS ";
|
|
}
|
|
if (wProductSuite & VER_SUITE_TERMINAL)
|
|
{
|
|
ResultStream << "VER_SUITE_TERMINAL ";
|
|
}
|
|
if (wProductSuite & VER_SUITE_SMALLBUSINESS_RESTRICTED)
|
|
{
|
|
ResultStream << "VER_SUITE_SMALLBUSINESS_RESTRICTED ";
|
|
}
|
|
if (wProductSuite & VER_SUITE_EMBEDDEDNT)
|
|
{
|
|
ResultStream << "VER_SUITE_EMBEDDEDNT ";
|
|
}
|
|
if (wProductSuite & VER_SUITE_DATACENTER)
|
|
{
|
|
ResultStream << "VER_SUITE_DATACENTER ";
|
|
}
|
|
if (wProductSuite & VER_SUITE_SINGLEUSERTS)
|
|
{
|
|
ResultStream << "VER_SUITE_SINGLEUSERTS ";
|
|
}
|
|
if (wProductSuite & VER_SUITE_PERSONAL)
|
|
{
|
|
ResultStream << "VER_SUITE_PERSONAL ";
|
|
}
|
|
return ePassed;
|
|
}
|
|
|
|
/*
|
|
TCHAR *IsServer ()
|
|
{
|
|
return IsItServer() ? _T("Its a Server") : _T("Its a WorkStation");
|
|
}
|
|
*/
|
|
|
|
|
|
|
|
EResult IsKernelTSEnable (ostrstream &ResultStream)
|
|
{
|
|
ASSERT(IsItLocalMachine());
|
|
if (IsTerminalServicesEnabled())
|
|
{
|
|
ResultStream << "Yes.";
|
|
return ePassed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "No.";
|
|
return eFailed;
|
|
}
|
|
}
|
|
|
|
bool TSEnabled ()
|
|
{
|
|
CRegistry reg;
|
|
if ( ERROR_SUCCESS == reg.OpenKey( HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Control\\Terminal Server"), KEY_READ, CTSTestData::GetMachineName()))
|
|
{
|
|
DWORD dwTSEnabled = 0;
|
|
if ( ERROR_SUCCESS == reg.ReadRegDWord( _T("TSEnabled"), &dwTSEnabled))
|
|
{
|
|
return dwTSEnabled == 1;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
EResult TSEnabled (ostrstream &ResultStream)
|
|
{
|
|
if (TSEnabled())
|
|
{
|
|
ResultStream << "Yes.";
|
|
return ePassed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "No.";
|
|
return eFailed;
|
|
}
|
|
}
|
|
|
|
EResult DoesProductSuiteContainTS (ostrstream &ResultStream)
|
|
{
|
|
if (DoesHydraKeysExists())
|
|
{
|
|
ResultStream << "Yes.";
|
|
return ePassed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "No.";
|
|
return eFailed;
|
|
}
|
|
}
|
|
|
|
EResult IsTerminalServerRegistryOk (ostrstream &ResultStream)
|
|
{
|
|
CRegistry reg1;
|
|
CRegistry reg2;
|
|
CRegistry reg3;
|
|
|
|
if (
|
|
(ERROR_SUCCESS == reg1.OpenKey(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Control\\Terminal Server"), KEY_READ, CTSTestData::GetMachineName())) &&
|
|
(ERROR_SUCCESS == reg2.OpenKey(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations"), KEY_READ, CTSTestData::GetMachineName())) &&
|
|
(ERROR_SUCCESS == reg3.OpenKey(HKEY_LOCAL_MACHINE, _T("Software\\Microsoft\\Windows NT\\CurrentVersion\\Terminal Server"), KEY_READ, CTSTestData::GetMachineName())))
|
|
{
|
|
ResultStream << "Yes.";
|
|
return ePassed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "No.";
|
|
return eFailed;
|
|
}
|
|
}
|
|
|
|
EResult GetWinstationList (ostrstream &ResultStream)
|
|
{
|
|
USES_CONVERSION;
|
|
CRegistry reg2;
|
|
|
|
bool bFoundNonConsoleWinstation = false;
|
|
|
|
if (ERROR_SUCCESS == reg2.OpenKey(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations"), KEY_READ, CTSTestData::GetMachineName()))
|
|
{
|
|
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)
|
|
{
|
|
ResultStream << ", ";
|
|
}
|
|
|
|
ResultStream << T2A(szWinstation);
|
|
bFirst = false;
|
|
}
|
|
while (ERROR_SUCCESS == reg2.GetNextSubKey(&szWinstation, &dwSize));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed to open winstations registry";
|
|
return eFailed;
|
|
}
|
|
|
|
if (!bFoundNonConsoleWinstation)
|
|
{
|
|
// ResultStream << "Error, Only Console Winstation found";
|
|
return eFailed;
|
|
}
|
|
else
|
|
{
|
|
return ePassed;
|
|
}
|
|
}
|
|
|
|
EResult IsTerminalServiceStartBitSet (ostrstream &ResultStream)
|
|
{
|
|
CRegistry reg;
|
|
if ( ERROR_SUCCESS == reg.OpenKey( HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\TermService"), KEY_READ, CTSTestData::GetMachineName()))
|
|
{
|
|
DWORD dwTermServStartBit = 0;
|
|
if ( ERROR_SUCCESS == reg.ReadRegDWord( _T("Start"), &dwTermServStartBit))
|
|
{
|
|
switch (dwTermServStartBit)
|
|
{
|
|
case 2:
|
|
ResultStream << "AutoStart";
|
|
break;
|
|
|
|
case 3:
|
|
ResultStream << "Manual Start";
|
|
break;
|
|
|
|
case 4:
|
|
ResultStream << "Error, Disabled";
|
|
break;
|
|
|
|
default:
|
|
ResultStream << "ERROR:Wrong value for startbit";
|
|
}
|
|
|
|
if (IsIt50TS())
|
|
{
|
|
if (2 == dwTermServStartBit)
|
|
return ePassed;
|
|
else
|
|
return eFailed;
|
|
}
|
|
else
|
|
{
|
|
if (IsIt51TS())
|
|
{
|
|
if (3 == dwTermServStartBit)
|
|
return ePassed;
|
|
else
|
|
return eFailed;
|
|
}
|
|
|
|
ResultStream << "what version of its is it ?";
|
|
return eFailedToExecute;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed to read startbit";
|
|
return eFailedToExecute;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed to read startbit";
|
|
return eFailedToExecute;
|
|
}
|
|
}
|
|
|
|
bool IsTermDDStartBitSet ()
|
|
{
|
|
CRegistry reg;
|
|
if ( ERROR_SUCCESS == reg.OpenKey( HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\TermDD"), KEY_READ, CTSTestData::GetMachineName()))
|
|
{
|
|
DWORD dwTermDDStartBit = 0;
|
|
if ( ERROR_SUCCESS == reg.ReadRegDWord( _T("Start"), &dwTermDDStartBit))
|
|
{
|
|
return dwTermDDStartBit == 2;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
EResult IsGroupPolicyOk (ostrstream &ResultStream)
|
|
{
|
|
CRegistry reg;
|
|
if (ERROR_SUCCESS == reg.OpenKey(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Policies\\Microsoft\\Windows NT\\Terminal Services"), KEY_READ, CTSTestData::GetMachineName()))
|
|
{
|
|
DWORD dwDenyConnections;
|
|
if (ERROR_SUCCESS == reg.ReadRegDWord(_T("fDenyTSConnections"), &dwDenyConnections))
|
|
{
|
|
if (dwDenyConnections == 0)
|
|
{
|
|
ResultStream << "Passed";
|
|
return ePassed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Group Policy does not allow connections";
|
|
return eFailed;
|
|
}
|
|
}
|
|
}
|
|
|
|
ResultStream << "Passed,Policy does not exist";
|
|
return ePassed;
|
|
|
|
}
|
|
|
|
/*
|
|
bool AreEffectiveConnectionAllowed ()
|
|
{
|
|
HMODULE hmodRegAPI = LoadLibrary( _T("RegApi.dll") );
|
|
|
|
if (hmodRegAPI)
|
|
{
|
|
typedef BOOLEAN (*PFDenyConnectionPolicy) ();
|
|
PFDenyConnectionPolicy pfnDenyConnectionPolicy;
|
|
|
|
pfnDenyConnectionPolicy = (PFDenyConnectionPolicy) GetProcAddress( hmodRegAPI, "RegDenyTSConnectionsPolicy");
|
|
if (pfnDenyConnectionPolicy)
|
|
{
|
|
return (*pfnDenyConnectionPolicy)() ? false : true;
|
|
|
|
}
|
|
else
|
|
{
|
|
szMoreInfo << "Failed to get proc RegDenyTSConnectionsPolicy" << endl;
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
szMoreInfo << "Failed to Load regapi.dll" << endl;
|
|
return false;
|
|
}
|
|
|
|
|
|
}
|
|
*/
|
|
|
|
EResult AreConnectionsAllowed(ostrstream &ResultStream)
|
|
{
|
|
DWORD dwError;
|
|
CRegistry oRegTermsrv;
|
|
|
|
dwError = oRegTermsrv.OpenKey(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Control\\Terminal Server"), KEY_READ, CTSTestData::GetMachineName());
|
|
if (ERROR_SUCCESS == dwError)
|
|
{
|
|
DWORD dwDenyConnect;
|
|
dwError = oRegTermsrv.ReadRegDWord(_T("fDenyTSConnections"), &dwDenyConnect);
|
|
if (ERROR_SUCCESS == dwError)
|
|
{
|
|
if (dwDenyConnect == 1)
|
|
{
|
|
ResultStream << "Failed, Connections are denied";
|
|
return eFailed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Passed, Connections are allowed";
|
|
return ePassed;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "failed to read value";
|
|
return eFailedToExecute;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "failed to open key";
|
|
return eFailedToExecute;
|
|
}
|
|
}
|
|
|
|
bool GetTSOCLogFileName(char *strFileName, UINT uiSize)
|
|
{
|
|
|
|
USES_CONVERSION;
|
|
if (CTSTestData::GetMachineName())
|
|
{
|
|
strcpy(strFileName, T2A(CTSTestData::GetMachineNamePath()));
|
|
strcat(strFileName, "\\admin$");
|
|
}
|
|
else
|
|
{
|
|
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.";
|
|
EResult DidTsOCgetCompleteInstallationMessage (ostrstream &ResultStream)
|
|
{
|
|
if (!IsTSOClogPresent())
|
|
{
|
|
ResultStream << "Failed because tsoc.log does not exist." << endl;
|
|
return eFailedToExecute;
|
|
}
|
|
|
|
char strTSOCLog[256];
|
|
GetTSOCLogFileName(strTSOCLog, 256);
|
|
|
|
ifstream ifSrc(strTSOCLog);
|
|
if(!ifSrc)
|
|
{
|
|
ResultStream << "Failed to open tsoc.log file." << endl;
|
|
return eFailedToExecute;
|
|
}
|
|
|
|
|
|
char tempSrc[256];
|
|
while(!ifSrc.eof())
|
|
{
|
|
ifSrc.getline(tempSrc, 256);
|
|
if (strstr(tempSrc, IncompleteMessage))
|
|
{
|
|
ResultStream << "Failed";
|
|
return eFailed;
|
|
}
|
|
}
|
|
|
|
ResultStream << "Passed";
|
|
return ePassed;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
EResult IsTSOClogPresent (ostrstream &ResultStream)
|
|
{
|
|
if (IsTSOClogPresent ())
|
|
{
|
|
ResultStream << "Passed";
|
|
return ePassed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed";
|
|
return eFailed;
|
|
}
|
|
|
|
}
|
|
|
|
EResult DidOCMInstallTSEnable(ostrstream &ResultStream)
|
|
{
|
|
CRegistry reg;
|
|
if ( ERROR_SUCCESS == reg.OpenKey( HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\OC Manager\\SubComponents"), KEY_READ, CTSTestData::GetMachineName()))
|
|
{
|
|
DWORD dwTSEnabled = 0;
|
|
if ( ERROR_SUCCESS == reg.ReadRegDWord( _T("tsenable"), &dwTSEnabled))
|
|
{
|
|
if (dwTSEnabled == 1)
|
|
{
|
|
ResultStream << "Passed";
|
|
return ePassed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed";
|
|
return eFailed;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed to open Value";
|
|
return eFailed;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed to open key";
|
|
return eFailedToExecute;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
EResult IsClusteringInstalled (ostrstream &ResultStream)
|
|
{
|
|
DWORD dwClusterState;
|
|
if (ERROR_SUCCESS == GetNodeClusterState(NULL, &dwClusterState))
|
|
{
|
|
if (dwClusterState != ClusterStateNotInstalled)
|
|
{
|
|
ResultStream << "***Failed. Clustering is installed.";
|
|
return eFailed;
|
|
}
|
|
|
|
}
|
|
|
|
ResultStream << "Passed.";
|
|
return ePassed;
|
|
}
|
|
|
|
|
|
EResult GetTSMode (ostrstream &ResultStream)
|
|
{
|
|
if (!IsItServer() && !IsRemoteAdminMode())
|
|
{
|
|
ResultStream << "ERROR:The machine is in app server Mode for Professional";
|
|
return eFailed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << (IsRemoteAdminMode() ? "Remote Admin" : "Application Server");
|
|
return ePassed;
|
|
}
|
|
}
|
|
|
|
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, CTSTestData::GetMachineName()))
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
|
|
// this return is bogus.
|
|
return true;
|
|
|
|
}
|
|
|
|
EResult VerifyModeRegistry (ostrstream &ResultStream)
|
|
{
|
|
if (CheckModeRegistry(!IsRemoteAdminMode(), ResultStream))
|
|
{
|
|
ResultStream << "Passed";
|
|
return ePassed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed";
|
|
return eFailed;
|
|
}
|
|
}
|
|
|
|
bool CheckModeRegistry (bool bAppCompat, ostrstream &ResultStream)
|
|
{
|
|
USES_CONVERSION;
|
|
bool bOk = true;
|
|
|
|
CRegistry reg;
|
|
|
|
if (IsItServer())
|
|
{
|
|
CRegistry reg1;
|
|
if ( ERROR_SUCCESS == reg1.OpenKey( HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"), KEY_READ, CTSTestData::GetMachineName()))
|
|
{
|
|
LPTSTR str;
|
|
DWORD dwSize;
|
|
if (ERROR_SUCCESS == reg1.ReadRegString(_T("AppSetup"), &str, &dwSize))
|
|
{
|
|
if (bAppCompat)
|
|
{
|
|
if (_tcsicmp(str, _T("UsrLogon.Cmd")) != 0)
|
|
{
|
|
bOk = false;
|
|
ResultStream << "ERROR: Wrong value (" << T2A(str) << ") for AppSetup, contact makarp/breenh" << endl;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if (_tcslen(str) != 0)
|
|
{
|
|
bOk = false;
|
|
ResultStream << "ERROR: Wrong value (" << T2A(str) << ") for AppSetup, contact makarp/breenh" << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "ERROR reading appsetup registry" << endl;
|
|
bOk = false;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "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, CTSTestData::GetMachineName()))
|
|
{
|
|
DWORD dwPriority;
|
|
if (ERROR_SUCCESS == reg.ReadRegDWord(_T("Win32PrioritySeparation"), &dwPriority))
|
|
{
|
|
if (bAppCompat)
|
|
{
|
|
if (0x26 != dwPriority)
|
|
{
|
|
bOk = false;
|
|
ResultStream << "ERROR: Wrong Win32PrioritySeparation (" << dwPriority << ")" << endl;
|
|
}
|
|
|
|
}
|
|
else if (IsItServer())
|
|
{
|
|
if (0x18 != dwPriority)
|
|
{
|
|
bOk = false;
|
|
ResultStream << "ERROR: Wrong Win32PrioritySeparation (" << dwPriority << ")" << endl;
|
|
}
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bOk = false;
|
|
ResultStream << "ERROR:Reading Win32PrioritySeparation registry" << endl;
|
|
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
bOk = false;
|
|
ResultStream << "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, CTSTestData::GetMachineName()))
|
|
{
|
|
DWORD dwIdleWinstations;
|
|
if (ERROR_SUCCESS == reg.ReadRegDWord(_T("IdleWinStationPoolCount"), &dwIdleWinstations))
|
|
{
|
|
if (bAppCompat)
|
|
{
|
|
if (0x2 != dwIdleWinstations)
|
|
{
|
|
bOk = false;
|
|
ResultStream << "ERROR: Wrong IdleWinStationPoolCount (" << dwIdleWinstations << ")" << endl;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if (0 != dwIdleWinstations)
|
|
{
|
|
bOk = false;
|
|
ResultStream << "ERROR: Wrong IdleWinStationPoolCount (" << dwIdleWinstations << ")" << endl;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
bOk = false;
|
|
ResultStream << "ERROR:Reading IdleWinStationPoolCount registry" << endl;
|
|
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
bOk = false;
|
|
ResultStream << "SYSTEM\\CurrentControlSet\\Control\\Terminal Server" << endl;
|
|
}
|
|
|
|
return bOk;
|
|
|
|
|
|
}
|
|
|
|
bool g_IsTermsrvRunning = false;
|
|
bool IsTerminalServiceRunning ()
|
|
{
|
|
return g_IsTermsrvRunning;
|
|
}
|
|
|
|
EResult IsTerminalServiceRunning (ostrstream &ResultStream)
|
|
{
|
|
EResult eRes = eUnknown;
|
|
bool bReturn = false;
|
|
|
|
SC_HANDLE hServiceController = OpenSCManager(CTSTestData::GetMachineNamePath(), 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);
|
|
if (bReturn)
|
|
{
|
|
ResultStream << "Passed";
|
|
eRes = ePassed;
|
|
g_IsTermsrvRunning = true;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed, Termsrv is not running";
|
|
eRes = eFailed;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed to get service status, Error = " << GetLastError();
|
|
eRes = eFailedToExecute;
|
|
}
|
|
|
|
VERIFY(CloseServiceHandle(hTermServ));
|
|
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed to open TermServ service, Error = " << GetLastError() << endl;
|
|
eRes = eFailedToExecute;
|
|
}
|
|
|
|
VERIFY(CloseServiceHandle(hServiceController));
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed to Open Service Controller, Error = " << GetLastError() << endl;
|
|
eRes = eFailedToExecute;
|
|
}
|
|
|
|
return eRes;
|
|
}
|
|
|
|
|
|
EResult CheckVideoKeys (ostrstream &ResultStream)
|
|
{
|
|
// 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, CTSTestData::GetMachineName()))
|
|
{
|
|
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"))))
|
|
{
|
|
ResultStream << "Passed";
|
|
return ePassed;
|
|
}
|
|
else
|
|
{
|
|
}
|
|
}
|
|
else
|
|
{
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
}
|
|
}
|
|
else
|
|
{
|
|
}
|
|
|
|
ResultStream << "Failed";
|
|
return eFailed;
|
|
}
|
|
|
|
TCHAR szCompName[256];
|
|
EResult GetCompName (ostrstream &ResultStream)
|
|
{
|
|
USES_CONVERSION;
|
|
if (!CTSTestData::GetMachineName())
|
|
{
|
|
|
|
DWORD dwCompName = 256;
|
|
if (GetComputerName(szCompName, &dwCompName))
|
|
{
|
|
ResultStream << T2A(szCompName);
|
|
return ePassed;
|
|
}
|
|
return eFailedToExecute;
|
|
}
|
|
else
|
|
{
|
|
_tcscpy(szCompName, CTSTestData::GetMachineName());
|
|
ResultStream << T2A(CTSTestData::GetMachineName());
|
|
return ePassed;
|
|
}
|
|
}
|
|
|
|
bool g_bIsInDomain = false;
|
|
EResult GetDomName (ostrstream &ResultStream)
|
|
{
|
|
USES_CONVERSION;
|
|
DSROLE_PRIMARY_DOMAIN_INFO_BASIC *pDomainInfo = NULL;
|
|
DWORD dwErr;
|
|
|
|
//
|
|
// Check if we're in a workgroup
|
|
//
|
|
dwErr = DsRoleGetPrimaryDomainInformation(CTSTestData::GetMachineName(),
|
|
DsRolePrimaryDomainInfoBasic,
|
|
(PBYTE *) &pDomainInfo);
|
|
|
|
if (ERROR_SUCCESS != dwErr)
|
|
{
|
|
ResultStream << "<Unknown Domain>";
|
|
return eFailedToExecute;
|
|
}
|
|
|
|
switch (pDomainInfo->MachineRole)
|
|
{
|
|
case DsRole_RoleStandaloneWorkstation:
|
|
case DsRole_RoleStandaloneServer:
|
|
ResultStream << "<Workgroup>";
|
|
return ePassed;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (pDomainInfo->DomainNameFlat)
|
|
{
|
|
ResultStream << T2A(pDomainInfo->DomainNameFlat);
|
|
g_bIsInDomain = true;
|
|
return ePassed;
|
|
}
|
|
else if (pDomainInfo->DomainNameDns)
|
|
{
|
|
ResultStream << T2A(pDomainInfo->DomainNameDns);
|
|
g_bIsInDomain = true;
|
|
return ePassed;
|
|
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "<Unknown Domain>";
|
|
return eFailedToExecute;
|
|
}
|
|
}
|
|
|
|
|
|
EResult GetIPAddress (ostrstream &ResultStream)
|
|
{
|
|
USES_CONVERSION;
|
|
WCHAR wszIPAddress[128];
|
|
//
|
|
//get host address
|
|
//
|
|
WORD wVersionRequested = MAKEWORD( 1, 1 );
|
|
WSADATA wsaData;
|
|
if (0 == WSAStartup(wVersionRequested,&wsaData))
|
|
{
|
|
hostent *h;
|
|
if (NULL != (h=gethostbyname ( T2A(CTSTestData::GetMachineName()) )))
|
|
{
|
|
in_addr *inaddr=(struct in_addr *)*h->h_addr_list;
|
|
|
|
MultiByteToWideChar(CP_ACP,0,inet_ntoa(*inaddr),-1,wszIPAddress,128);
|
|
ResultStream << W2A(wszIPAddress);
|
|
return ePassed;
|
|
|
|
}
|
|
}
|
|
|
|
ResultStream << "Error Getting IP";
|
|
return eFailedToExecute;
|
|
}
|
|
|
|
|
|
|
|
EResult IsRDPNPinNetProviders (ostrstream &ResultStream)
|
|
// 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, CTSTestData::GetMachineName())) &&
|
|
(ERROR_SUCCESS == regNetOrder.ReadRegString(PROVIDER_ORDER_VALUE, &szOldValue, &dwSize)))
|
|
{
|
|
bRdpNpExists = (_tcsstr(szOldValue, RDPNP_ENTRY) != NULL);
|
|
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Error: Failed to Read Registry!";
|
|
return eFailedToExecute;
|
|
}
|
|
|
|
if (TSEnabled () == bRdpNpExists)
|
|
{
|
|
ResultStream << "Passed";
|
|
return ePassed;
|
|
}
|
|
else
|
|
{
|
|
if (bRdpNpExists)
|
|
{
|
|
ResultStream << "Error: RDPNP, exists in ProviderOrder, but TS is disabled!";
|
|
return eFailed;
|
|
}
|
|
else
|
|
{
|
|
if (IsIt50TS())
|
|
{
|
|
// rdp np is only for 51+ so its ok if its missing for 50.
|
|
ResultStream << "Passed";
|
|
return ePassed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "ERROR, RDPNP is missing from ProviderOrder";
|
|
return eFailed;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
EResult IsMultiConnectionAllowed (ostrstream &ResultStream)
|
|
// 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, CTSTestData::GetMachineName())) &&
|
|
(ERROR_SUCCESS == regWL.ReadRegDWord(_T("AllowMultipleTSSessions"), &dwAllowMultipal)))
|
|
{
|
|
if (dwAllowMultipal)
|
|
{
|
|
ResultStream << "Yes";
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "No";
|
|
}
|
|
|
|
return ePassed;
|
|
}
|
|
|
|
if (IsIt50TS())
|
|
{
|
|
ResultStream << "Yes";
|
|
return ePassed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "ERROR, registry missing";
|
|
return eFailedToExecute;
|
|
}
|
|
}
|
|
|
|
EResult LogonType (ostrstream &ResultStream)
|
|
// TCHAR *LogonType ()
|
|
{
|
|
if (!g_bIsInDomain)
|
|
{
|
|
CRegistry regWL;
|
|
DWORD dwLogonType;
|
|
if ((ERROR_SUCCESS == regWL.OpenKey(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"), KEY_READ, CTSTestData::GetMachineName())) &&
|
|
(ERROR_SUCCESS == regWL.ReadRegDWord(_T("LogonType"), &dwLogonType)))
|
|
{
|
|
if (dwLogonType == 0)
|
|
{
|
|
ResultStream << "Classic Gina";
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "New Fancy";
|
|
}
|
|
return ePassed;
|
|
}
|
|
|
|
if (IsIt50TS())
|
|
{
|
|
ResultStream << "Classic Gina";
|
|
return ePassed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "ERROR, registry missing";
|
|
return eFailedToExecute;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Classic Gina";
|
|
return ePassed;
|
|
}
|
|
}
|
|
|
|
EResult IsTermSrvInSystemContext (ostrstream &ResultStream)
|
|
// bool IsTermSrvInSystemContext ()
|
|
{
|
|
USES_CONVERSION;
|
|
CRegistry reg;
|
|
if ( ERROR_SUCCESS == reg.OpenKey( HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\TermService"), KEY_READ, CTSTestData::GetMachineName()))
|
|
{
|
|
TCHAR *szObjectName;
|
|
DWORD dwSize;
|
|
if ( ERROR_SUCCESS == reg.ReadRegString( _T("ObjectName"), &szObjectName, &dwSize))
|
|
{
|
|
if (0 == _tcsicmp(szObjectName, _T("LocalSystem")))
|
|
{
|
|
ResultStream << "Passed";
|
|
return ePassed;
|
|
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "ERROR:Termsrv is set to run using (" << T2A(szObjectName) << ") context." << endl;
|
|
return eFailed;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "failed to read Objectname";
|
|
return eFailedToExecute;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "failed to open termsrv registry";
|
|
return eFailedToExecute;
|
|
}
|
|
}
|
|
EResult IsBetaSystem (ostrstream &ResultStream)
|
|
{
|
|
ASSERT (IsItLocalMachine());
|
|
if (IsBetaSystem())
|
|
{
|
|
ResultStream << "Its a beta system";
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Its a retail build";
|
|
}
|
|
|
|
return ePassed;
|
|
}
|
|
|
|
EResult AreRemoteLogonEnabled (ostrstream &ResultStream)
|
|
{
|
|
CRegistry oRegTermsrv;
|
|
if (ERROR_SUCCESS == oRegTermsrv.OpenKey(
|
|
HKEY_LOCAL_MACHINE,
|
|
_T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"),
|
|
KEY_READ,
|
|
CTSTestData::GetMachineName()
|
|
))
|
|
{
|
|
DWORD dwSize = 0;
|
|
LPTSTR szWinstationDisabled = NULL;
|
|
if (ERROR_SUCCESS == oRegTermsrv.ReadRegString(_T("WinStationsDisabled"), &szWinstationDisabled, &dwSize))
|
|
{
|
|
if (_tcscmp(_T("0"), szWinstationDisabled) == 0)
|
|
{
|
|
ResultStream << "Passed";
|
|
return ePassed;
|
|
}
|
|
else
|
|
{
|
|
USES_CONVERSION;
|
|
ResultStream << "Failed, WinStationsDisabled is (" << T2A(szWinstationDisabled) << ")";
|
|
return eFailed;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed to red registry";
|
|
return eFailedToExecute;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed to read registry";
|
|
return eFailedToExecute;
|
|
}
|
|
|
|
}
|
|
|
|
EResult IsListenerSessionPresent(ostrstream &ResultStream)
|
|
{
|
|
PWTS_SESSION_INFO pWtsSessionInfo;
|
|
DWORD dwCount;
|
|
bool bReturn = false;
|
|
|
|
|
|
HANDLE hServer = WTS_CURRENT_SERVER_HANDLE;
|
|
if (CTSTestData::GetMachineName())
|
|
{
|
|
TCHAR szMachineName[256];
|
|
_tcscpy(szMachineName, CTSTestData::GetMachineName());
|
|
hServer = WTSOpenServer (szMachineName);
|
|
}
|
|
|
|
if (WTSEnumerateSessions(
|
|
hServer,
|
|
0,
|
|
1,
|
|
&pWtsSessionInfo,
|
|
&dwCount
|
|
))
|
|
{
|
|
for (DWORD i = 0; i < dwCount; i++)
|
|
{
|
|
if (pWtsSessionInfo[i].State == WTSListen)
|
|
{
|
|
bReturn = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
WTSFreeMemory(pWtsSessionInfo);
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "WTSEnumerateSessions failed!";
|
|
return eFailedToExecute;
|
|
}
|
|
|
|
if (CTSTestData::GetMachineName())
|
|
WTSCloseServer(hServer);
|
|
|
|
if (bReturn)
|
|
{
|
|
ResultStream << "Passed!";
|
|
return ePassed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed!";
|
|
return eFailed;
|
|
}
|
|
}
|
|
|
|
|
|
ULONG ulClientBuildNumber = 0xffffffff;
|
|
bool GetClientVersion(ULONG *pulClientBuildNumber)
|
|
{
|
|
ASSERT(AreWeInsideSession());
|
|
ASSERT(pulClientBuildNumber);
|
|
if (ulClientBuildNumber == 0xffffffff)
|
|
{
|
|
LPTSTR pBuffer = NULL;
|
|
DWORD dwBytesReturned = 0;
|
|
if (WTSQuerySessionInformation(
|
|
WTS_CURRENT_SERVER_HANDLE,
|
|
WTS_CURRENT_SESSION,
|
|
WTSClientBuildNumber,
|
|
&pBuffer,
|
|
&dwBytesReturned))
|
|
{
|
|
if (pBuffer && dwBytesReturned)
|
|
{
|
|
ulClientBuildNumber = ULONG(*pBuffer);
|
|
*pulClientBuildNumber = ulClientBuildNumber;
|
|
WTSFreeMemory(pBuffer);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*pulClientBuildNumber = ulClientBuildNumber;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
USHORT gusClientProtocol = 0xffff;
|
|
bool GetClientProtocol (USHORT *pusClientProtocol)
|
|
{
|
|
ASSERT(AreWeInsideSession());
|
|
ASSERT(pusClientProtocol);
|
|
if (gusClientProtocol == 0xffff)
|
|
{
|
|
LPTSTR pBuffer = NULL;
|
|
DWORD dwBytesReturned = 0;
|
|
if (WTSQuerySessionInformation(
|
|
WTS_CURRENT_SERVER_HANDLE,
|
|
WTS_CURRENT_SESSION,
|
|
WTSClientProtocolType,
|
|
&pBuffer,
|
|
&dwBytesReturned))
|
|
{
|
|
if (pBuffer && dwBytesReturned)
|
|
{
|
|
gusClientProtocol = USHORT(*pBuffer);
|
|
*pusClientProtocol = gusClientProtocol;
|
|
WTSFreeMemory(pBuffer);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*pusClientProtocol = gusClientProtocol;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
EResult GetClientVersion(ostrstream &ResultStream)
|
|
{
|
|
ULONG ulClientVersion;
|
|
ASSERT(AreWeInsideSession());
|
|
if (GetClientVersion(&ulClientVersion))
|
|
{
|
|
ResultStream << ulClientVersion;
|
|
return ePassed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed to retrive client version";
|
|
return eFailedToExecute;
|
|
}
|
|
|
|
}
|
|
|
|
EResult GetClientProtocol(ostrstream &ResultStream)
|
|
{
|
|
USHORT usClientProtocol;
|
|
ASSERT(AreWeInsideSession());
|
|
if (GetClientProtocol(&usClientProtocol))
|
|
{
|
|
switch (usClientProtocol)
|
|
{
|
|
case WTS_PROTOCOL_TYPE_CONSOLE:
|
|
ResultStream << "WTS_PROTOCOL_TYPE_CONSOLE(" << usClientProtocol << ")";
|
|
break;
|
|
case WTS_PROTOCOL_TYPE_ICA:
|
|
ResultStream << "WTS_PROTOCOL_TYPE_ICA(" << usClientProtocol << ")";
|
|
break;
|
|
case WTS_PROTOCOL_TYPE_RDP:
|
|
ResultStream << "WTS_PROTOCOL_TYPE_RDP(" << usClientProtocol << ")";
|
|
break;
|
|
default:
|
|
ResultStream << "Unknown Protocol Value(" << usClientProtocol << ")";
|
|
break;
|
|
}
|
|
return ePassed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed to retrive client protocol";
|
|
return eFailedToExecute;
|
|
}
|
|
}
|
|
|
|
|
|
EResult DoesClientSupportAudioRedirection (ostrstream &ResultStream)
|
|
{
|
|
ASSERT(AreWeInsideSession());
|
|
|
|
const USHORT GOOD_CLIENT_VERSION_FOR_AUDIO_REDIRECTION = 2252;
|
|
ULONG ulClientVersion;
|
|
USHORT usClientProtocol;
|
|
|
|
if (GetClientVersion(&ulClientVersion) && GetClientProtocol(&usClientProtocol))
|
|
{
|
|
if (ulClientVersion >= GOOD_CLIENT_VERSION_FOR_AUDIO_REDIRECTION && usClientProtocol == WTS_PROTOCOL_TYPE_RDP)
|
|
{
|
|
ResultStream << "Passed";
|
|
return ePassed;
|
|
}
|
|
else
|
|
{
|
|
if (ulClientVersion < GOOD_CLIENT_VERSION_FOR_AUDIO_REDIRECTION )
|
|
{
|
|
ResultStream << "Failed. You client is old, it does not support audio redirection.";
|
|
}
|
|
else if(usClientProtocol != WTS_PROTOCOL_TYPE_RDP)
|
|
{
|
|
ResultStream << "Failed. You client is not Microsoft RDP, it may not support audio redirection.";
|
|
}
|
|
else
|
|
{
|
|
ASSERT(false);
|
|
}
|
|
|
|
return eFailed;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed to get client version";
|
|
return eFailedToExecute;
|
|
}
|
|
}
|
|
|
|
EResult DoesClientSupportPrinterRedirection (ostrstream &ResultStream)
|
|
{
|
|
ASSERT(AreWeInsideSession());
|
|
|
|
const USHORT GOOD_CLIENT_VERSION_FOR_PRINTER_REDIRECTION = 2100; // BUGBUG :get good value for this from tADB
|
|
ULONG ulClientVersion;
|
|
USHORT usClientProtocol;
|
|
|
|
if (GetClientVersion(&ulClientVersion) && GetClientProtocol(&usClientProtocol))
|
|
{
|
|
if (ulClientVersion >= GOOD_CLIENT_VERSION_FOR_PRINTER_REDIRECTION && usClientProtocol == WTS_PROTOCOL_TYPE_RDP)
|
|
{
|
|
ResultStream << "Passed";
|
|
return ePassed;
|
|
}
|
|
else
|
|
{
|
|
if (ulClientVersion < GOOD_CLIENT_VERSION_FOR_PRINTER_REDIRECTION )
|
|
{
|
|
ResultStream << "Failed. You client is old, it does not support printer redirection.";
|
|
}
|
|
else if(usClientProtocol != WTS_PROTOCOL_TYPE_RDP)
|
|
{
|
|
ResultStream << "Failed. You client is not Microsoft RDP, it may not support printer redirection.";
|
|
}
|
|
else
|
|
{
|
|
ASSERT(false);
|
|
}
|
|
|
|
return eFailed;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed to get client version";
|
|
return eFailedToExecute;
|
|
}
|
|
}
|
|
|
|
EResult DoesClientSupportFileRedirection (ostrstream &ResultStream)
|
|
{
|
|
ASSERT(AreWeInsideSession());
|
|
|
|
const USHORT GOOD_CLIENT_VERSION_FOR_FILE_REDIRECTION = 2200; // BUGBUG :get good value for this from tADB
|
|
ULONG ulClientVersion;
|
|
USHORT usClientProtocol;
|
|
|
|
if (GetClientVersion(&ulClientVersion) && GetClientProtocol(&usClientProtocol))
|
|
{
|
|
if (ulClientVersion >= GOOD_CLIENT_VERSION_FOR_FILE_REDIRECTION && usClientProtocol == WTS_PROTOCOL_TYPE_RDP)
|
|
{
|
|
ResultStream << "Passed";
|
|
return ePassed;
|
|
}
|
|
else
|
|
{
|
|
if (ulClientVersion < GOOD_CLIENT_VERSION_FOR_FILE_REDIRECTION )
|
|
{
|
|
ResultStream << "Failed. You client is old, it does not support file redirection.";
|
|
}
|
|
else if(usClientProtocol != WTS_PROTOCOL_TYPE_RDP)
|
|
{
|
|
ResultStream << "Failed. You client is not Microsoft RDP, it may not support file redirection.";
|
|
}
|
|
else
|
|
{
|
|
ASSERT(false);
|
|
}
|
|
|
|
return eFailed;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed to get client version";
|
|
return eFailedToExecute;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
EResult DoesClientSupportClipboardRedirection (ostrstream &ResultStream)
|
|
{
|
|
ASSERT(AreWeInsideSession());
|
|
|
|
const USHORT GOOD_CLIENT_VERSION_FOR_FILE_REDIRECTION = 2100; // BUGBUG :get good value for this from Nadim
|
|
ULONG ulClientVersion;
|
|
USHORT usClientProtocol;
|
|
|
|
if (GetClientVersion(&ulClientVersion) && GetClientProtocol(&usClientProtocol))
|
|
{
|
|
if (ulClientVersion >= GOOD_CLIENT_VERSION_FOR_FILE_REDIRECTION && usClientProtocol == WTS_PROTOCOL_TYPE_RDP)
|
|
{
|
|
ResultStream << "Passed";
|
|
return ePassed;
|
|
}
|
|
else
|
|
{
|
|
if (ulClientVersion < GOOD_CLIENT_VERSION_FOR_FILE_REDIRECTION )
|
|
{
|
|
ResultStream << "Failed. You client is old, it does not support Clipboard redirection.";
|
|
}
|
|
else if(usClientProtocol != WTS_PROTOCOL_TYPE_RDP)
|
|
{
|
|
ResultStream << "Failed. You client is not Microsoft RDP, it may not support Clipboard redirection.";
|
|
}
|
|
else
|
|
{
|
|
ASSERT(false);
|
|
}
|
|
|
|
return eFailed;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed to get client version";
|
|
return eFailedToExecute;
|
|
}
|
|
}
|
|
|
|
// #define TS_POLICY_SUB_TREE L"Software\\Policies\\Microsoft\\Windows NT\\Terminal Services"
|
|
|
|
|
|
bool GetWinstationInformation(WINSTATIONINFORMATION **ppInfo)
|
|
{
|
|
ASSERT(ppInfo);
|
|
ASSERT(AreWeInsideSession());
|
|
static bool sbGotWinstaInfo = false;
|
|
static WINSTATIONINFORMATION WSInfo;
|
|
ULONG ReturnLength;
|
|
|
|
if (sbGotWinstaInfo)
|
|
{
|
|
*ppInfo = &WSInfo;
|
|
return true;
|
|
}
|
|
|
|
if (WinStationQueryInformation(
|
|
WTS_CURRENT_SERVER_HANDLE,
|
|
WTS_CURRENT_SESSION,
|
|
WinStationInformation,
|
|
&WSInfo,
|
|
sizeof(WSInfo),
|
|
&ReturnLength
|
|
))
|
|
{
|
|
sbGotWinstaInfo = true;
|
|
*ppInfo = &WSInfo;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool GetWinstationConfiguration (WINSTATIONCONFIG **ppInfo)
|
|
{
|
|
ASSERT(ppInfo);
|
|
ASSERT(AreWeInsideSession());
|
|
static bool sbGotWinstaConfig = false;
|
|
static WINSTATIONCONFIG WSConfig;
|
|
ULONG ReturnLength;
|
|
|
|
if (sbGotWinstaConfig)
|
|
{
|
|
*ppInfo = &WSConfig;
|
|
return true;
|
|
}
|
|
|
|
if (WinStationQueryInformation(
|
|
WTS_CURRENT_SERVER_HANDLE,
|
|
WTS_CURRENT_SESSION,
|
|
WinStationConfiguration,
|
|
&WSConfig,
|
|
sizeof(WSConfig),
|
|
&ReturnLength
|
|
))
|
|
{
|
|
sbGotWinstaConfig = true;
|
|
*ppInfo = &WSConfig;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
EResult GetUserName(ostrstream &ResultStream)
|
|
{
|
|
USES_CONVERSION;
|
|
ASSERT(AreWeInsideSession());
|
|
WINSTATIONINFORMATION *pWSInfo = NULL;
|
|
|
|
if (GetWinstationInformation(&pWSInfo))
|
|
{
|
|
TCHAR szUser[256];
|
|
_tcscpy(szUser, pWSInfo->Domain);
|
|
_tcscat(szUser, _T("\\"));
|
|
_tcscat(szUser, pWSInfo->UserName);
|
|
ResultStream << T2A(szUser);
|
|
return ePassed;
|
|
}
|
|
|
|
ResultStream << "Failed to get UserName";
|
|
return eFailedToExecute;
|
|
}
|
|
|
|
EResult GetPolicy (ostrstream &ResultStream)
|
|
{
|
|
USES_CONVERSION;
|
|
ASSERT(AreWeInsideSession());
|
|
WINSTATIONCONFIG *pWSInfo = NULL;
|
|
|
|
if (GetWinstationConfiguration(&pWSInfo))
|
|
{
|
|
/*
|
|
ResultStream << "fPromptForPassword" << pWSInfo->User.fPromptForPassword << "," << endl;
|
|
ResultStream << "fResetBroken" << pWSInfo->User.fResetBroken << "," << endl;
|
|
ResultStream << "fReconnectSame " << pWSInfo->User.fReconnectSame << "," << endl;
|
|
ResultStream << "fLogonDisabled " << pWSInfo->User.fLogonDisabled << "," << endl;;
|
|
ResultStream << "fWallPaperDisabled" << pWSInfo->User.fWallPaperDisabled << "," << endl;
|
|
ResultStream << "fAutoClientDrives" << pWSInfo->User.fAutoClientDrives << "," << endl;
|
|
ResultStream << "fAutoClientLpts" << pWSInfo->User.fAutoClientLpts << "," << endl;
|
|
ResultStream << "fForceClientLptDef" << pWSInfo->User.fForceClientLptDef << "," << endl;
|
|
ResultStream << "fRequireEncryption" << pWSInfo->User.fRequireEncryption << "," << endl;
|
|
ResultStream << "fDisableEncryption" << pWSInfo->User.fDisableEncryption << "," << endl;
|
|
ResultStream << "fUnused1" << pWSInfo->User.fUnused1 << "," << endl;
|
|
ResultStream << "fHomeDirectoryMapRoot" << pWSInfo->User.fHomeDirectoryMapRoot << "," << endl;
|
|
ResultStream << "fUseDefaultGina" << pWSInfo->User.fUseDefaultGina << "," << endl;
|
|
*/
|
|
|
|
/*
|
|
ULONG fDisableCpm : 1;
|
|
for printing
|
|
ULONG fDisableCdm : 1;
|
|
for drive
|
|
ULONG fDisableCcm : 1;
|
|
for com port
|
|
ULONG fDisableLPT : 1;
|
|
for lpt port
|
|
ULONG fDisableClip : 1;
|
|
for clipboard redirection
|
|
ULONG fDisableExe : 1;
|
|
|
|
ULONG fDisableCam : 1;
|
|
for audio redirection
|
|
|
|
ULONG ColorDepth : 3;
|
|
Color depth.
|
|
|
|
*/
|
|
ResultStream << "printer redirection = " << pWSInfo->User.fDisableCpm << endl;
|
|
ResultStream << "drive redirection = " << pWSInfo->User.fDisableCdm << endl;
|
|
ResultStream << "com port redirection = " << pWSInfo->User.fDisableCcm << endl;
|
|
ResultStream << "LPT port redirection = " << pWSInfo->User.fDisableLPT << endl;
|
|
ResultStream << "Clipboard redirection =" << pWSInfo->User.fDisableClip << endl;
|
|
ResultStream << "fDisableExe = " << pWSInfo->User.fDisableExe << endl;
|
|
ResultStream << "Audio Redireciton = " << pWSInfo->User.fDisableCam << endl;
|
|
|
|
return ePassed;
|
|
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed to get config data";
|
|
return eFailedToExecute;
|
|
}
|
|
}
|
|
|
|
EResult CanRedirectPrinter (ostrstream &ResultStream)
|
|
{
|
|
USES_CONVERSION;
|
|
ASSERT(AreWeInsideSession());
|
|
WINSTATIONCONFIG *pWSInfo = NULL;
|
|
|
|
if (GetWinstationConfiguration(&pWSInfo))
|
|
{
|
|
if (pWSInfo->User.fDisableCpm)
|
|
{
|
|
ResultStream << "Failed. Printer Redirection is disabled either by Group Policy or TSCC settings.";
|
|
return eFailed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Passed";
|
|
return ePassed;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed to retrive config data";
|
|
return eFailedToExecute;
|
|
}
|
|
}
|
|
|
|
EResult CanRedirectDrives(ostrstream &ResultStream)
|
|
{
|
|
USES_CONVERSION;
|
|
ASSERT(AreWeInsideSession());
|
|
WINSTATIONCONFIG *pWSInfo = NULL;
|
|
|
|
if (GetWinstationConfiguration(&pWSInfo))
|
|
{
|
|
if (pWSInfo->User.fDisableCdm)
|
|
{
|
|
ResultStream << "Failed. Local Drive Redirection is disabled either by Group Policy or TSCC settings.";
|
|
return eFailed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Passed";
|
|
return ePassed;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed to retrive config data";
|
|
return eFailedToExecute;
|
|
}
|
|
}
|
|
|
|
EResult CanRedirectClipboard(ostrstream &ResultStream)
|
|
{
|
|
USES_CONVERSION;
|
|
ASSERT(AreWeInsideSession());
|
|
WINSTATIONCONFIG *pWSInfo = NULL;
|
|
|
|
if (GetWinstationConfiguration(&pWSInfo))
|
|
{
|
|
if (pWSInfo->User.fDisableClip)
|
|
{
|
|
ResultStream << "Failed. Clipboard redirection is disabled either by Group Policy or TSCC settings.";
|
|
return eFailed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Passed";
|
|
return ePassed;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed to retrive config data";
|
|
return eFailedToExecute;
|
|
}
|
|
}
|
|
|
|
EResult CanRedirectCom(ostrstream &ResultStream)
|
|
{
|
|
USES_CONVERSION;
|
|
ASSERT(AreWeInsideSession());
|
|
WINSTATIONCONFIG *pWSInfo = NULL;
|
|
|
|
if (GetWinstationConfiguration(&pWSInfo))
|
|
{
|
|
if (pWSInfo->User.fDisableCcm)
|
|
{
|
|
ResultStream << "Failed. Com port Redirection is disabled either by Group Policy or TSCC settings.";
|
|
return eFailed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Passed";
|
|
return ePassed;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed to retrive config data";
|
|
return eFailedToExecute;
|
|
}
|
|
}
|
|
|
|
EResult CanRedirectAudio(ostrstream &ResultStream)
|
|
{
|
|
USES_CONVERSION;
|
|
ASSERT(AreWeInsideSession());
|
|
WINSTATIONCONFIG *pWSInfo = NULL;
|
|
|
|
if (GetWinstationConfiguration(&pWSInfo))
|
|
{
|
|
if (pWSInfo->User.fDisableCam)
|
|
{
|
|
ResultStream << "Failed. Audio Redirection is disabled either by Group Policy or TSCC settings.";
|
|
return eFailed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Passed";
|
|
return ePassed;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed to retrive config data";
|
|
return eFailedToExecute;
|
|
}
|
|
}
|
|
|
|
EResult CanClientPlayAudio(ostrstream &ResultStream)
|
|
{
|
|
EResult rv = eFailedToExecute;
|
|
HANDLE hStream = NULL;
|
|
PSNDSTREAM Stream = NULL;
|
|
|
|
hStream = OpenFileMapping(
|
|
FILE_MAP_ALL_ACCESS,
|
|
FALSE,
|
|
TSSND_STREAMNAME
|
|
);
|
|
|
|
if (NULL == hStream)
|
|
{
|
|
ResultStream << "Can't open audio stream";
|
|
goto exitpt;
|
|
}
|
|
|
|
Stream = (PSNDSTREAM)MapViewOfFile(
|
|
hStream,
|
|
FILE_MAP_ALL_ACCESS,
|
|
0, 0, // offset
|
|
sizeof(*Stream)
|
|
);
|
|
|
|
if (NULL == Stream)
|
|
{
|
|
ResultStream << "Can't lock audio stream memory";
|
|
goto exitpt;
|
|
}
|
|
|
|
if ( 0 != (TSSNDCAPS_ALIVE & Stream->dwSoundCaps) )
|
|
{
|
|
ResultStream << "Passed";
|
|
rv = ePassed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Client doesn't have audio hardware or audio redirection is not enabled on the client side";
|
|
rv = eFailed;
|
|
}
|
|
|
|
exitpt:
|
|
|
|
if ( NULL != Stream )
|
|
UnmapViewOfFile( Stream );
|
|
|
|
if ( NULL != hStream )
|
|
CloseHandle( hStream );
|
|
|
|
return rv;
|
|
}
|
|
|
|
EResult NotConsoleAudio( ostrstream &ResultStream )
|
|
{
|
|
EResult rv = eFailedToExecute;
|
|
|
|
|
|
if (NtCurrentPeb()->SessionId == 0 || IsItPTS())
|
|
{
|
|
HANDLE hConsoleAudioEvent = OpenEvent(SYNCHRONIZE, FALSE, L"Global\\WinMMConsoleAudioEvent");
|
|
|
|
if (hConsoleAudioEvent != NULL)
|
|
{
|
|
DWORD status = WaitForSingleObject(hConsoleAudioEvent, 0);
|
|
|
|
if (status == WAIT_OBJECT_0)
|
|
{
|
|
ResultStream << "Client audio settings are: Leave at remote computer";
|
|
rv = eFailed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Passed";
|
|
rv = ePassed;
|
|
}
|
|
|
|
CloseHandle(hConsoleAudioEvent);
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed to open Global\\WinMMConsoleAudioEvent";
|
|
rv = eFailedToExecute;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Not running on remote console or Whistler Professional";
|
|
rv = ePassed;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
EResult CanRedirectLPT (ostrstream &ResultStream)
|
|
{
|
|
USES_CONVERSION;
|
|
ASSERT(AreWeInsideSession());
|
|
WINSTATIONCONFIG *pWSInfo = NULL;
|
|
|
|
if (GetWinstationConfiguration(&pWSInfo))
|
|
{
|
|
if (pWSInfo->User.fDisableLPT)
|
|
{
|
|
ResultStream << "Failed. LPT port Redirection is disabled either by Group Policy or TSCC settings.";
|
|
return eFailed;
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Passed";
|
|
return ePassed;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ResultStream << "Failed to retrive config data";
|
|
return eFailedToExecute;
|
|
}
|
|
}
|
|
|
|
bool CanRunAllTests()
|
|
{
|
|
return DoIHaveEnufPermissions();
|
|
}
|
|
|
|
bool CanRunGeneralInfo ()
|
|
{
|
|
return DoIHaveEnufPermissions();
|
|
}
|
|
bool CanRunCantConnect ()
|
|
{
|
|
return (CanPing() && DoIHaveEnufPermissions());
|
|
}
|
|
bool CanRunCantPrint ()
|
|
{
|
|
return AreWeInsideSession();
|
|
}
|
|
bool CanRunCantCopyPaste ()
|
|
{
|
|
return AreWeInsideSession();
|
|
}
|
|
bool CanRunFileRedirect ()
|
|
{
|
|
return AreWeInsideSession();
|
|
}
|
|
bool CanRunLptRedirect ()
|
|
{
|
|
return AreWeInsideSession();
|
|
}
|
|
bool CanRunComRedirect ()
|
|
{
|
|
return AreWeInsideSession();
|
|
}
|
|
bool CanRunAudioRedirect ()
|
|
{
|
|
return AreWeInsideSession();
|
|
}
|
|
|
|
TCHAR *WhyCantRunAllTests()
|
|
{
|
|
ASSERT(!CanRunAllTests());
|
|
if (!DoIHaveEnufPermissions())
|
|
{
|
|
return _T("You do not have sufficient permissions to run this test against target system.");
|
|
}
|
|
else
|
|
{
|
|
ASSERT(false);
|
|
return _T("WhyCantRunAllTests");
|
|
}
|
|
}
|
|
TCHAR *WhyCantRunGeneralInfo()
|
|
{
|
|
ASSERT(!CanRunGeneralInfo());
|
|
if (!DoIHaveEnufPermissions())
|
|
{
|
|
return _T("You do not have sufficient permissions to run this test against target system.");
|
|
}
|
|
else
|
|
{
|
|
ASSERT(false);
|
|
return _T("WhyCantRunGeneralInfo");
|
|
}
|
|
}
|
|
TCHAR *WhyCantRunCantConnect()
|
|
{
|
|
ASSERT(!CanRunCantConnect());
|
|
if (!CanPing())
|
|
{
|
|
return _T("Ping test Failed for target machine. Please make sure target machine is on the network");
|
|
}
|
|
if (!DoIHaveEnufPermissions())
|
|
{
|
|
return _T("You do not have sufficient permissions to run this test against target system.");
|
|
}
|
|
else
|
|
{
|
|
ASSERT(false);
|
|
return _T("WhyCantRunCantConnect");
|
|
}
|
|
}
|
|
TCHAR *WhyCantRunCantPrint()
|
|
{
|
|
ASSERT(!CanRunCantPrint());
|
|
if (!AreWeInsideSession())
|
|
{
|
|
return _T("For diagnosing this problem, you mush run these troubleshooter within the session. Plese create a remote desktop session to the target machine, and then troubleshoot");
|
|
}
|
|
else
|
|
{
|
|
ASSERT(false);
|
|
return _T("WhyCantRunCantPrint");
|
|
}
|
|
|
|
}
|
|
TCHAR *WhyCantRunCantCopyPaste()
|
|
{
|
|
ASSERT(!CanRunCantCopyPaste());
|
|
if (!AreWeInsideSession())
|
|
{
|
|
return _T("For diagnosing this problem, you mush run these troubleshooter within the session. Plese create a remote desktop session to the target machine, and then troubleshoot");
|
|
}
|
|
else
|
|
{
|
|
ASSERT(false);
|
|
return _T("WhyCantRunCantCopyPaste");
|
|
}
|
|
}
|
|
TCHAR *WhyCantRunFileRedirect()
|
|
{
|
|
ASSERT(!CanRunFileRedirect());
|
|
if (!AreWeInsideSession())
|
|
{
|
|
return _T("For diagnosing this problem, you mush run these troubleshooter within the session. Plese create a remote desktop session to the target machine, and then troubleshoot");
|
|
}
|
|
else
|
|
{
|
|
ASSERT(false);
|
|
return _T("WhyCantRunFileRedirect");
|
|
}
|
|
}
|
|
TCHAR *WhyCantRunLptRedirect()
|
|
{
|
|
ASSERT(!CanRunLptRedirect());
|
|
if (!AreWeInsideSession())
|
|
{
|
|
return _T("For diagnosing this problem, you mush run these troubleshooter within the session. Plese create a remote desktop session to the target machine, and then troubleshoot");
|
|
}
|
|
else
|
|
{
|
|
ASSERT(false);
|
|
return _T("WhyCantRunLptRedirect");
|
|
}
|
|
}
|
|
TCHAR *WhyCantRunComRedirect()
|
|
{
|
|
ASSERT(!CanRunComRedirect());
|
|
if (!AreWeInsideSession())
|
|
{
|
|
return _T("For diagnosing this problem, you mush run these troubleshooter within the session. Plese create a remote desktop session to the target machine, and then troubleshoot");
|
|
}
|
|
else
|
|
{
|
|
ASSERT(false);
|
|
return _T("WhyCantRunComRedirect");
|
|
}
|
|
}
|
|
TCHAR *WhyCantRunAudioRedirect()
|
|
{
|
|
ASSERT(!CanRunAudioRedirect());
|
|
if (!AreWeInsideSession())
|
|
{
|
|
return _T("For diagnosing this problem, you mush run these troubleshooter within the session. Plese create a remote desktop session to the target machine, and then troubleshoot");
|
|
}
|
|
else
|
|
{
|
|
ASSERT(false);
|
|
return _T("WhyCantRunAudioRedirect");
|
|
}
|
|
}
|
|
|