windows-nt/Source/XPSP1/NT/enduser/windows.com/wuv3/wudetect/filever.cpp

429 lines
13 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
#include "wudetect.h"
/////////////////////////////////////////////////////////////////////////////
// CExpressionParser::dwKeyType
//
//
// Parameters:
//
// Comments :
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// Class CExpressionParser
// Function fKeyType
//---------------------------------------------------------------------------
//
// Return Value --- TRUE if key type match made, FALSE if no match made
// Parameter
// TCHAR* szRootType --- [IN] string contains the value of key type
// HKEY* phkey --- [OUT] retrieved key type value
/////////////////////////////////////////////////////////////////////////////
//
// Modified by RogerJ, 03/09/00
// Original Creator Unknown
// Modification --- UNICODE and Win64 ready
//
/////////////////////////////////////////////////////////////////////////////
bool CExpressionParser::fKeyType(TCHAR *szRootType, HKEY *phKey)
{
bool fError = false;
if ( lstrcmpi(HKEY_LOCAL_MACHINE_ROOT, szRootType) == 0 )
{
*phKey = HKEY_LOCAL_MACHINE;
}
else if ( lstrcmpi(HKEY_CURRENT_USER_ROOT, szRootType) == 0 )
{
*phKey = HKEY_CURRENT_USER;
}
else if ( lstrcmpi(HKEY_CLASSES_ROOT_ROOT, szRootType) == 0 )
{
*phKey = HKEY_CLASSES_ROOT;
}
else if ( lstrcmpi(HKEY_CURRENT_CONFIG_ROOT, szRootType) == 0 )
{
*phKey = HKEY_CURRENT_CONFIG;
}
else if ( lstrcmpi(HKEY_USERS_ROOT, szRootType) == 0 )
{
*phKey = HKEY_USERS;
}
else if ( lstrcmpi(HKEY_PERFORMANCE_DATA_ROOT, szRootType) == 0 )
{
*phKey = HKEY_PERFORMANCE_DATA;
}
else if ( lstrcmpi(HKEY_DYN_DATA_ROOT, szRootType) == 0 )
{
*phKey = HKEY_DYN_DATA;
}
else
{
fError = true;
}
return fError;
}
/////////////////////////////////////////////////////////////////////////////
// CExpressionParser::fDetectRegSubStr
// Detect a substring in registry datum.
//
// Form: E=RegSubstr,<SubStr>,<RootKey>,<KeyPath>,<RegValue>,<RegData>
//
// Comments :
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// This function is not modifed to be UNICODE ready, since it is not compiled
/////////////////////////////////////////////////////////////////////////////
#if 0
bool CExpressionParser::fDetectRegSubStr(TCHAR * pszBuf)
{
DWORD dwInstallStatus = DET_NOTINSTALLED;
HKEY hKeyRoot;
HKEY hKey;
DWORD type;
char szTargetKeyName[MAX_PATH];
char szTargetKeyValue[MAX_PATH];
char szKeyMissingStatus[MAX_PATH];
char szData[MAX_PATH];
char szSubStr[MAX_PATH];
char szBuf[MAX_PATH];
// get the registry key name from the components section of the
// CIF file.
if ( FGetCifEntry(pDetection, DETREG_KEY, szBuf, sizeof(szBuf)) &&
(dwKeyType(szBuf, &hKeyRoot, szTargetKeyName, sizeof(szTargetKeyName)) == ERROR_SUCCESS) )
{
if ( RegOpenKeyEx( hKeyRoot,
szTargetKeyName,
0,
KEY_QUERY_VALUE,
&hKey) == ERROR_SUCCESS )
{
if ( FGetCifEntry(pDetection, DETREG_SUBSTR, szBuf, sizeof(szBuf)) &&
(GetStringField2(szBuf, 0, szTargetKeyValue, sizeof(szTargetKeyValue)) != 0) &&
(GetStringField2(szBuf, 1, szKeyMissingStatus, sizeof(szKeyMissingStatus)) != 0) )
{
DWORD size = sizeof(szData);
if ( RegQueryValueEx(hKey,
szTargetKeyValue,
0,
&type,
(BYTE *)szData,
&size) == ERROR_SUCCESS )
{
if ( type == REG_SZ )
{
_strlwr(szData);
// iterate thru the substrings looking for a match.
int index = 2;
while ( GetStringField2(szBuf, index, szSubStr, sizeof(szSubStr)) != 0 )
{
_strlwr(szSubStr);
if ( strstr(szData, szSubStr) != NULL )
{
*pDetection->pdwInstalledVer = 1;
*pDetection->pdwInstalledBuild = 1;
dwInstallStatus = DET_INSTALLED;
goto quit_while;
}
index++;
}
quit_while:;
}
}
else
{
// if we get an error, assume the key does not exist. Note that if
// the status is DETFIELD_NOT_INSTALLED then we don't have to do
// anything since that is the default status.
if ( lstrcmpi(DETFIELD_INSTALLED, szKeyMissingStatus) == 0 )
{
dwInstallStatus = DET_INSTALLED;
}
}
}
RegCloseKey(hKey);
}
}
cleanup:
return dwInstallStatus;
return false;
}
#endif
/////////////////////////////////////////////////////////////////////////////
// CExpressionParser::fMapComparisonToken
// Detect file version.
//
// Form: _E1=FileVer,sysdir,ntdll.dll,=,4.06.00.0407,4.06.00.0407
//
// Comments :
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// Class CExpressionParser
// Function fMapComparisonToken
//---------------------------------------------------------------------------
//
// Return Value --- TRUE if a matching is found, FALSE otherwise
// Parameter
// TCHAR* pszComparisonToken --- [IN] the token need to find a match
// enumToken* penToken --- [OUT] token enum value found, if no token found, the value is undetermined
/////////////////////////////////////////////////////////////////////////////
//
// Modified by RogerJ, 03/09/00
// Original Creator Unkown
// Modification --- UNICODE and Win64 ready
//
/////////////////////////////////////////////////////////////////////////////
bool CExpressionParser::fMapComparisonToken(TCHAR *pszComparisonToken,
enumToken *penToken)
{
static TokenMapping grComparisonTokenMap[] =
{
{TEXT("="), COMP_EQUALS},
{TEXT("!="), COMP_NOT_EQUALS},
{TEXT("<"), COMP_LESS_THAN},
{TEXT("<="), COMP_LESS_THAN_EQUALS},
{TEXT(">"), COMP_GREATER_THAN},
{TEXT(">="), COMP_GREATER_THAN_EQUALS}
};
return fMapToken(pszComparisonToken,
sizeof(grComparisonTokenMap)/sizeof(grComparisonTokenMap[0]),
grComparisonTokenMap,
penToken);
}
/////////////////////////////////////////////////////////////////////////////
// CExpressionParser::fMapRootDirToken
// Detect file version.
//
// Form: _E1=FileVer,sysdir,ntdll.dll,=,4.06.00.0407,4.06.00.0407
//
// Comments :
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// Class CExpressionParser
// Function fMapRootDirToken
//---------------------------------------------------------------------------
//
// Return Value --- TRUE if a matching is found, FALSE otherwise
// Parameter
// TCHAR* pszRootDirToken --- [IN] the token need to find a match
// enumToken* penToken --- [OUT] token enum value found, if no token found, the value is undetermined
/////////////////////////////////////////////////////////////////////////////
//
// Modified by RogerJ, 03/09/00
// Original Creator Unkown
// Modification --- UNICODE and Win64 ready
//
/////////////////////////////////////////////////////////////////////////////
bool CExpressionParser::fMapRootDirToken(TCHAR *pszRootDirToken, enumToken *penToken)
{
static TokenMapping grDirectoryTokenMap[] =
{
{TEXT("sysdir"), DIR_SYSTEM},
{TEXT("windir"), DIR_WINDOWS},
};
return fMapToken(pszRootDirToken,
sizeof(grDirectoryTokenMap)/sizeof(grDirectoryTokenMap[0]),
grDirectoryTokenMap,
penToken);
}
/////////////////////////////////////////////////////////////////////////////
// CExpressionParser::fMapToken
// Detect file version.
//
// Form: _E1=FileVer,sysdir,ntdll.dll,=,4.06.00.0407,4.06.00.0407
//
// Comments :
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// Class CExpressionParser
// Function fMapToken
//---------------------------------------------------------------------------
//
// Return Value --- TRUE if a matching is found, FALSE otherwise
// Parameter
// TCHAR* pszToken --- [IN] the token need to find a match
// int nSize --- [IN] number of tokens to be matched as the template
// TokenMapping grTokenMap[] --- [IN] token template to be matched
// enumToken* penToken --- [OUT] token enum value found, if no token found, the value is undetermined
/////////////////////////////////////////////////////////////////////////////
//
// Modified by RogerJ, 03/09/00
// Original Creator Unkown
// Modification --- UNICODE and Win64 ready
//
/////////////////////////////////////////////////////////////////////////////
bool CExpressionParser::fMapToken(TCHAR *pszToken,
int nSize,
TokenMapping grTokenMap[],
enumToken *penToken)
{
for ( int index = 0; index < nSize; index++ )
{
if ( _tcscmp(pszToken, grTokenMap[index].pszToken) == 0 )
{
*penToken = grTokenMap[index].enToken;
return true;
}
}
return false;
}
/////////////////////////////////////////////////////////////////////////////
// CExpressionParser::fDetectFileVer
// Detect file version.
//
// Form: _E1=FileVer,sysdir,ntdll.dll,=,4.06.00.0407,4.06.00.0407
//
// Comments :
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// Class CExpressionParser
// Function fDetectFileVer
//---------------------------------------------------------------------------
//
// Return Value --- TRUE if version of input files matched the file version in the system, FALSE otherwise
// Parameter
// TCHAR* pszBuf --- [IN] the name of the input file
//////////////////////////////////////////////////////////////////////////////
//
// Modified by RogerJ, 03/09/00
// Original Creator Unkown
// Modification --- UNICODE and Win64 ready
//
/////////////////////////////////////////////////////////////////////////////
const DWORD WU_MAX_COMPARISON_LEN = 3;
const DWORD WU_MAX_VERSION_LEN = 30;
bool CExpressionParser::fDetectFileVer(TCHAR * pszBuf)
{
bool fResult = false;
TCHAR szRootDir[MAX_PATH];
TCHAR szFile[MAX_PATH];
TCHAR szFilePath[MAX_PATH];
TCHAR szComparison[WU_MAX_COMPARISON_LEN];
TCHAR szVersion[WU_MAX_VERSION_LEN];
enumToken enComparisonToken;
enumToken enRootDirToken;
// Get reg root type (HKLM, etc)
if ( (GetStringField2(pszBuf, 1, szRootDir, sizeof(szRootDir)/sizeof(TCHAR)) != 0) &&
(GetStringField2(pszBuf, 2, szFile, sizeof(szFile)/sizeof(TCHAR)) != 0) &&
fMapRootDirToken(szRootDir, &enRootDirToken) )
{
// create the file path
if ( enRootDirToken == DIR_SYSTEM )
{
if ( GetSystemDirectory(szFilePath, sizeof(szFilePath)/sizeof(TCHAR)) == 0 )
return false;
}
else // DIR_WINDOWS
{
if ( GetWindowsDirectory(szFilePath, sizeof(szFilePath)/sizeof(TCHAR)) == 0 )
return false;
}
if (szFilePath[_tcslen(szFilePath)-1]!='\\') _tcscat(szFilePath, TEXT("\\"));
_tcscat(szFilePath, szFile);
if ( (GetStringField2(pszBuf, 3, szComparison, sizeof(szComparison)/sizeof(TCHAR)) != 0) &&
fMapComparisonToken(szComparison, &enComparisonToken) )
{
DWORD dwSize;
DWORD dwReserved;
DWORD dwVer, dwBuild;
VS_FIXEDFILEINFO *pVerInfo;
UINT uLen;
dwSize = GetFileVersionInfoSize(szFilePath, &dwReserved);
if ( dwSize > 0)
{
TCHAR *pbVerInfo = (TCHAR *)malloc(dwSize);
if ( GetFileVersionInfo(szFilePath, dwReserved, dwSize, pbVerInfo) &&
(VerQueryValue(pbVerInfo, TEXT("\\"), (void **)&pVerInfo, &uLen) != 0) )
{
for ( int index = 4;
!fResult && (GetStringField2(pszBuf, index, szVersion, sizeof(szVersion)/sizeof(TCHAR)) != 0);
index++ )
{
fConvertDotVersionStrToDwords(szVersion, &dwVer, &dwBuild);
// do version comparison
switch ( enComparisonToken )
{
case COMP_EQUALS:
fResult = (pVerInfo->dwProductVersionMS == dwVer) &&
(pVerInfo->dwProductVersionLS == dwBuild);
break;
case COMP_NOT_EQUALS:
fResult = (pVerInfo->dwProductVersionMS != dwVer) ||
(pVerInfo->dwProductVersionLS != dwBuild);
break;
case COMP_LESS_THAN:
fResult = (pVerInfo->dwProductVersionMS < dwVer) ||
((pVerInfo->dwProductVersionMS == dwVer) &&
(pVerInfo->dwProductVersionLS < dwBuild));
break;
case COMP_LESS_THAN_EQUALS:
fResult = (pVerInfo->dwProductVersionMS < dwVer) ||
((pVerInfo->dwProductVersionMS == dwVer) &&
(pVerInfo->dwProductVersionLS <= dwBuild));
break;
case COMP_GREATER_THAN:
fResult = (pVerInfo->dwProductVersionMS > dwVer) ||
((pVerInfo->dwProductVersionMS == dwVer) &&
(pVerInfo->dwProductVersionLS > dwBuild));
break;
case COMP_GREATER_THAN_EQUALS:
fResult = (pVerInfo->dwProductVersionMS > dwVer) ||
((pVerInfo->dwProductVersionMS == dwVer) &&
(pVerInfo->dwProductVersionLS >= dwBuild));
break;
}
}
}
free(pbVerInfo);
}
}
else
{
// just a file existence check.
fResult = (_taccess(szFilePath, 0) != -1);
}
}
return fResult;
}