windows-nt/Source/XPSP1/NT/enduser/windows.com/wuv3/wudetect/expression.cpp
2020-09-26 16:20:57 +08:00

383 lines
8.8 KiB
C++

/////////////////////////////////////////////////////////////////
//
// File Modified by RogerJ, 03/09/00
//
/////////////////////////////////////////////////////////////////
#include "wudetect.h"
const TCHAR DET_TYPE_FILEVERSION[] = TEXT("FileVer");
const TCHAR DET_TYPE_REGKEYEXISTS[] = TEXT("RegKeyExists");
const TCHAR DET_TYPE_REGKEYSUBSTR[] = TEXT("RegKeySubStr");
const TCHAR DET_TYPE_REGKEYBINARY[] = TEXT("RegKeyBinary");
const TCHAR DET_TYPE_REGKEYVERSION[] = TEXT("RegKeyVersion");
const TCHAR DET_TYPE_40BITSEC[] = TEXT("40BitSec");
void CExpressionParser::vSkipWS(void)
{
while ( ( *m_pch==' ' ) || ( *m_pch=='\t') )
{
m_pch++;
}
}
bool CExpressionParser::fGetCurToken( PARSE_TOKEN_TYPE & tok,
TOKEN_IDENTIFIER *grTokens,
int nSize)
{
bool fError = true;
int index;
vSkipWS();
TCHAR *pchStart = m_pch;
for ( index = 0; index < nSize; index++ )
{
TCHAR *pchTok = grTokens[index].pszTok;
while ( ( *pchTok==*m_pch ) && ( *pchTok!='\0' ) && ( *m_pch!='\0' ) )
{
m_pch++;
pchTok++;
}
if ( *pchTok=='\0' )
{
// match
fError = false;
tok = grTokens[index].tok;
break;
}
else if ( *m_pch == '\0' )
{
fError = false;
tok = TOKEN_DONE;
}
}
if ( (pchStart == m_pch) && (TOKEN_DONE != tok) )
{
// we haven't moved at all so this must be a variable.
fError = false;
tok = TOKEN_VARIABLE;
}
//done:
return fError;
}
bool CExpressionParser::fGetCurTermToken(PARSE_TOKEN_TYPE & tok)
{
static TOKEN_IDENTIFIER grTermTokens[] = {
{TEXT("("), TOKEN_LEFTPAREN},
{TEXT(")"), TOKEN_RIGHTPAREN},
{TEXT("!"), TOKEN_NOT}
};
bool fError = fGetCurToken(tok, grTermTokens, sizeof(grTermTokens)/sizeof(TOKEN_IDENTIFIER));
if ( !fError && (TOKEN_DONE == tok) )
{
fError = true;
}
return fError;
}
bool CExpressionParser::fGetCurExprToken(PARSE_TOKEN_TYPE & tok)
{
static TOKEN_IDENTIFIER grExprTokens[] = {
{TEXT("&&"), TOKEN_AND},
{TEXT("||"), TOKEN_OR}
};
return fGetCurToken(tok, grExprTokens, sizeof(grExprTokens)/sizeof(TOKEN_IDENTIFIER));
}
bool CExpressionParser::fGetVariable(TCHAR *pszVariable)
{
bool fError = false;
TCHAR *pchEnd = m_pch;
while ( _istdigit(*pchEnd) || _istalpha(*pchEnd) )
{
pchEnd++;
}
if ( pchEnd == m_pch )
{
fError = true;
}
else
{
// pointers in IA64 is 64 bits. The third argument of this function
// requires an int (32 bits). Since the variable name should be always
// has a length within 32 bits, a static cast should have no problem.
lstrcpyn(pszVariable, m_pch, (int)(pchEnd - m_pch + 1));
m_pch = pchEnd;
}
return fError;
}
/////////////////////////////////////////////////////////////////////////////
// fGetCifEntry
// Get an entry from the CIF file.
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// Class CExpressionParser
// Function fGetCifEntry
//---------------------------------------------------------------------------
//
// Return Value --- TRUE if Successfully retrieved CIF file value
// FALSE if failed
// Parameter
// TCHAR* pszParamName --- [IN] Name of the CIF file
// TCHAR* pszParamValue --- [OUT] Value of the CIF file
// DWORD cbParamValue --- size of the pszParamValue in TCHAR
// NOTE: This function calls GetCustomData to retrieve the value of CIF file
// GetCustomData is defined in inseng.h which takes only ANSI strings.
// Thus, UNICODE version of this function needed to convert parameters
// to and from ANSI compatibles.
//
/////////////////////////////////////////////////////////////////////////////
//
// Modified by RogerJ, 03/09/00
// Original Creator Unknown (YanL?)
// Modification --- UNICODE and Win64 enabled
//
/////////////////////////////////////////////////////////////////////////////
bool CExpressionParser::fGetCifEntry(
TCHAR *pszParamName,
TCHAR *pszParamValue,
DWORD cbParamValue)
// pszParamName is [IN], pszParamValue is [OUT], the function GetCustomData requires
// LPSTR for both parameters, string conversion is necessary in the UNICODE case
{
#ifdef _UNICODE
bool fSucceed;
int nLengthOfpszParamName;
char *pszParamNameANSI;
char *pszParamValueANSI;
nLengthOfpszParamName = lstrlen(pszParamName)+1; // including the NULL character
//
// NTBUG9#161019 PREFIX:leaking memory - waltw 8/16/00
// Free ANSI buffers before return in all cases via unicodeExit.
// Also fixed potentially dangerous conversion of uninitialized [OUT] parameter
// and wasteful conversion of [IN] parameter
//
pszParamValueANSI = (char *) malloc(cbParamValue*sizeof(char));
pszParamNameANSI = (char *) malloc(sizeof(char)*nLengthOfpszParamName);
if ((NULL == pszParamValueANSI) || (NULL == pszParamNameANSI))
{
fSucceed = FALSE;
goto unicodeExit;
}
// do UNICODE to ANSI string conversion
wcstombs(pszParamNameANSI,pszParamName,nLengthOfpszParamName);
// wcstombs(pszParamValueANSI,pszParamValue,cbParamValue); // Uninitialized [OUT] buffer - don't convert!
// make actual function call
fSucceed= (ERROR_SUCCESS == m_pDetection->pCifComp->GetCustomData(pszParamNameANSI,
pszParamValueANSI,
cbParamValue));
// do ANSI to UNICODE string conversion
// mbstowcs(pszParamName,pszParamNameANSI,nLengthOfpszParamName); // [IN] param not modified by GetCustomData
mbstowcs(pszParamValue,pszParamValueANSI,cbParamValue);
unicodeExit:
if (NULL != pszParamValueANSI)
{
free(pszParamValueANSI);
}
if (NULL != pszParamNameANSI)
{
free(pszParamNameANSI);
}
return fSucceed;
#else
return (ERROR_SUCCESS == m_pDetection->pCifComp->GetCustomData(pszParamName,
pszParamValue,
cbParamValue));
#endif
}
bool CExpressionParser::fPerformDetection(TCHAR * pszVariable, bool & fResult)
{
bool fError = false;
TCHAR szBuf[MAX_PATH];
TCHAR szDetection[MAX_PATH];
if ( fGetCifEntry(pszVariable, szBuf, sizeof(szBuf)/sizeof(TCHAR)) )
{
if ( GetStringField2(szBuf, 0, szDetection, sizeof(szDetection)/sizeof(TCHAR)) != 0)
{
if ( lstrcmpi(szDetection, DET_TYPE_FILEVERSION) == 0 )
{
fResult = fDetectFileVer(szBuf);
}
else if ( lstrcmpi(szDetection, DET_TYPE_REGKEYEXISTS) == 0 )
{
fResult = fDetectRegKeyExists(szBuf);
}
else if ( lstrcmpi(szDetection, DET_TYPE_REGKEYSUBSTR) == 0 )
{
fResult = fDetectRegSubStr(szBuf);
}
else if ( lstrcmpi(szDetection, DET_TYPE_REGKEYBINARY) == 0 )
{
fResult = fDetectRegBinary(szBuf);
}
else if ( lstrcmpi(szDetection, DET_TYPE_REGKEYVERSION) == 0 )
{
fResult = fDetectRegKeyVersion(szBuf);
}
else if ( lstrcmpi(szDetection, DET_TYPE_40BITSEC) == 0 )
{
fResult = fDetect40BitSecurity(szBuf);
}
}
}
return fError;
}
bool CExpressionParser::fEvalTerm(bool & fResult, bool fSkip)
{
PARSE_TOKEN_TYPE tok;
bool fError = fGetCurTermToken(tok);
if ( fError ) goto done;
if ( TOKEN_LEFTPAREN == tok )
{
fError = fEvalExpr(fResult);
if ( fError ) goto done;
fError = fGetCurTermToken(tok);
if ( fError ) goto done;
if ( TOKEN_RIGHTPAREN != tok )
{
fError = true;
}
}
else if ( TOKEN_NOT == tok )
{
fError = fEvalTerm(fResult, false);
if ( fError ) goto done;
fResult = !fResult;
}
else // TOKEN_VARIABLE == tok
{
TCHAR szVariable[MAX_PATH];
fError = fGetVariable(szVariable);
if ( fError ) goto done;
if ( !fSkip )
{
fError = fPerformDetection(szVariable, fResult);
if ( fError ) goto done;
}
}
done:
return fError;
}
HRESULT CExpressionParser::fEvalExpression(TCHAR * pszExpr,
bool * pfResult)
{
HRESULT hr = S_OK;
m_pch = pszExpr;
if ( fEvalExpr(*pfResult) )
{
hr = E_FAIL;
}
return hr;
}
bool CExpressionParser::fEvalExpr(bool & fResult)
{
bool fTmpResult;
PARSE_TOKEN_TYPE tok;
bool fError = fEvalTerm(fResult, false);
if ( fError ) goto done;
while ( TRUE )
{
fError = fGetCurExprToken(tok);
if ( fError ) goto done;
if ( TOKEN_AND == tok )
{
fError = fEvalTerm(fTmpResult, !fResult);
if ( fError ) goto done;
if ( fResult )
{
fResult = fResult && fTmpResult;
}
}
else if ( TOKEN_OR == tok )
{
fError = fEvalTerm(fTmpResult, fResult);
if ( fError ) goto done;
if ( !fResult )
{
fResult = fResult || fTmpResult;
}
}
else // if ( TOKEN_DONE == tok )
{
break;
}
}
done:
return fError;
}
// The codes Under this line is not compiled, so they are not UNICODE ready
#if 0
void Evaluate(TCHAR *pszExpr)
{
bool fResult;
HRESULT hr = fEvalExpression(pszExpr, &fResult);
if ( FAILED(hr) )
printf("%s == ERROR\n", pszExpr);
else
printf("%s == %c\n", pszExpr, fResult ? 'T' : 'F');
}
int main()
{
Evaluate(TEXT("((T && F) || !F || T)"));
Evaluate(TEXT("F || F || (T && T && F)"));
Evaluate(TEXT("((T && F) || !F || T)"));
Evaluate(TEXT(""));
Evaluate(TEXT("T"));
Evaluate(TEXT("F||T"));
Evaluate(TEXT("!F"));
return 0;
}
#endif