//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1996 - 2000. // // File: express.cxx // // Contents: Used to parse and evaluate IF expressions // // History: 96/Jan/3 DwightKr Created // //---------------------------------------------------------------------------- #include #pragma hdrstop // Copied from propvar.h #define BSTRLEN(bstrVal) *((ULONG *) bstrVal - 1) //+--------------------------------------------------------------------------- // // Function: IsEmpty (DBCS version), private // // Arguments: [pszVal] -- string to search // [cc] -- size (in chars) of string // // Returns; TRUE if string is empty (all chars in string space-like things) // // History: 28-Jun-96 KyleP created // //---------------------------------------------------------------------------- BOOL IsEmpty( char const * pszVal, unsigned cc ) { // // Optimize for the common case: non-empty strings // WORD aCharType[10]; unsigned ccProcessed = 0; while ( ccProcessed < cc ) { unsigned ccThisPass = (unsigned)min( sizeof(aCharType)/sizeof(aCharType[0]), cc - ccProcessed ); if ( !GetStringTypeExA( LOCALE_SYSTEM_DEFAULT, CT_CTYPE1, pszVal + ccProcessed, ccThisPass, aCharType ) ) { ciGibDebugOut(( DEB_ERROR, "Error %d from GetStringTypeExA\n", GetLastError() )); return FALSE; } for ( unsigned i = 0; i < ccThisPass; i++ ) { if ( (aCharType[i] & (C1_SPACE | C1_CNTRL | C1_BLANK)) == 0 ) return FALSE; } ccProcessed += ccThisPass; } return TRUE; } //+--------------------------------------------------------------------------- // // Function: IsEmpty (UniCode version), private // // Arguments: [pwszVal] -- string to search // [cc] -- size (in chars) of string // // Returns; TRUE if string is empty (all chars in string space-like things) // // History: 28-Jun-96 KyleP created // //---------------------------------------------------------------------------- BOOL IsEmpty( WCHAR const * pwszVal, unsigned cc ) { // // Optimize for the common case: non-empty strings // WORD aCharType[10]; unsigned ccProcessed = 0; while ( ccProcessed < cc ) { unsigned ccThisPass = (unsigned)min( sizeof(aCharType)/sizeof(aCharType[0]), cc - ccProcessed ); // // NOTE: the unicode version of GetStringTypeEx ignores the locale // if ( !GetStringTypeExW( LOCALE_SYSTEM_DEFAULT, CT_CTYPE1, pwszVal + ccProcessed, ccThisPass, aCharType ) ) { ciGibDebugOut(( DEB_ERROR, "Error %d from GetStringTypeExA\n", GetLastError() )); return FALSE; } for ( unsigned i = 0; i < ccThisPass; i++ ) { if ( (aCharType[i] & (C1_SPACE | C1_CNTRL | C1_BLANK)) == 0 ) return FALSE; } ccProcessed += ccThisPass; } return TRUE; } //+--------------------------------------------------------------------------- // // Function: StringToSystemTime // // Synopsis: Read a SystemTime from a string // // Arguments: [wcsSystemTime] - system time to parse // [stUTC] - resulting system time // // Returns TRUE if the coearcion was possible, FALSE otherwise. // // History: 96/Jun/27 DwightKr created // //---------------------------------------------------------------------------- static BOOL StringToSystemTime( WCHAR const * wcsSystemTime, SYSTEMTIME & stUTC ) { if ( 0 == wcsSystemTime ) { return FALSE; } stUTC.wHour = 0; stUTC.wMinute = 0; stUTC.wSecond = 0; stUTC.wMilliseconds = 0; int cItems = swscanf( wcsSystemTime, L"%4hd/%2hd/%2hd %2hd:%2hd:%2hd:%3hd", &stUTC.wYear, &stUTC.wMonth, &stUTC.wDay, &stUTC.wHour, &stUTC.wMinute, &stUTC.wSecond, &stUTC.wMilliseconds ); return (cItems >= 3); } //+--------------------------------------------------------------------------- // // Function: StringToFileTime // // Synopsis: Read a FileTime from a string // // Arguments: [wcsSystemTime] - system time to parse // [filetime] - resulting file time // // Returns TRUE if the coearcion was possible, FALSE otherwise. // // History: 96/Jun/27 DwightKr created // //---------------------------------------------------------------------------- static BOOL StringToFileTime( WCHAR const * wcsSystemTime, FILETIME & fileTime ) { SYSTEMTIME stUTC; if ( !StringToSystemTime( wcsSystemTime, stUTC ) ) { return FALSE; } return SystemTimeToFileTime( &stUTC, &fileTime ); } //+--------------------------------------------------------------------------- // // Function: VectorCoerce // // Synopsis: Coerce's the type of a vector // // Arguments: [Value] - value to coerce // [type] - final type desired // // Returns TRUE if the coearcion was possible, FALSE otherwise. // // History: 96/Jun/27 DwightKr created // //---------------------------------------------------------------------------- static BOOL VectorCoerce( CHTXIfExpressionValue & Value, VARTYPE type, PROPVARIANT & propVariant ) { ULONG size = Value.GetValue()->cal.cElems; _int64 i64Value; unsigned _int64 ui64Value; double dblValue; switch (type) { case VT_LPSTR | VT_VECTOR: { XCoMem aStr( size ); for (unsigned i=0; i pszStringValue; if ( !Value.GetVectorValueStr(i, pszStringValue ) ) { return FALSE; } aStr[i] = pszStringValue.Acquire(); } propVariant.calpstr.cElems = size; propVariant.calpstr.pElems = (PCHAR *) aStr.Acquire(); } break; case VT_LPWSTR | VT_VECTOR: { XCoMem aWStr( size ); for (unsigned i=0; i wszStringValue; if ( !Value.GetVectorValueWStr(i, wszStringValue) ) { return FALSE; } aWStr[i] = wszStringValue.Acquire(); } propVariant.calpwstr.cElems = size; propVariant.calpwstr.pElems = aWStr.Acquire(); } break; case VT_BSTR | VT_VECTOR: { XCoMem aBStr( size ); for (unsigned i=0; i aUI1( size ); for (unsigned i=0; i UCHAR_MAX ) { return FALSE; } aUI1[i] = (BYTE) ui64Value; } propVariant.caub.cElems = size; propVariant.caub.pElems = aUI1.Acquire(); } break; case VT_I1 | VT_VECTOR: { XCoMem aI1( size ); for (unsigned i=0; i SCHAR_MAX) ) { return FALSE; } aI1[i] = (BYTE) i64Value; } propVariant.caub.cElems = size; propVariant.caub.pElems = aI1.Acquire(); } break; case VT_UI2 | VT_VECTOR: { XCoMem aUI2( size ); for (unsigned i=0; i USHRT_MAX) ) { return FALSE; } aUI2[i] = (USHORT) ui64Value; } propVariant.caui.cElems = size; propVariant.caui.pElems = (USHORT *) aUI2.Acquire(); } break; case VT_I2 | VT_VECTOR: { XCoMem aI2( size ); for (unsigned i=0; i SHRT_MAX) ) { return FALSE; } aI2[i] = (SHORT) i64Value; } propVariant.cai.cElems = size; propVariant.cai.pElems = aI2.Acquire(); } break; case VT_UI4 | VT_VECTOR: { XCoMem aUI4( size ); for (unsigned i=0; i ULONG_MAX) ) { return FALSE; } aUI4[i] = (ULONG) ui64Value; } propVariant.caul.cElems = size; propVariant.caul.pElems = aUI4.Acquire(); } break; case VT_I4 | VT_VECTOR: { XCoMem aI4( size ); for (unsigned i=0; i LONG_MAX) ) { return FALSE; } aI4[i] = (LONG) i64Value; } propVariant.cal.cElems = size; propVariant.cal.pElems = aI4.Acquire(); } break; case VT_UI8 | VT_VECTOR: case VT_I8 | VT_VECTOR: { // // hVal used instead of uhVal because latter coercion // is not yet supported by x86 compiler. // XCoMem aUI8( size ); for (unsigned i=0; i aR4( size ); for (unsigned i=0; i FLT_MAX) ) { return FALSE; } aR4[i] = (float) dblValue; } propVariant.caflt.cElems = size; propVariant.caflt.pElems = aR4.Acquire(); } break; case VT_R8 | VT_VECTOR: { XCoMem aR8( size ); for (unsigned i=0; i aBOOL( size ); for (unsigned i=0; icalpwstr.pElems[i], L"TRUE") == 0) || (_wcsicmp(Value.GetValue()->calpwstr.pElems[i], L"T") == 0) ) { aBOOL[i] = VARIANT_TRUE; } else if ( (_wcsicmp(Value.GetValue()->calpwstr.pElems[i], L"FALSE") == 0) || (_wcsicmp(Value.GetValue()->calpwstr.pElems[i], L"F") == 0) ) { aBOOL[i] = VARIANT_FALSE; } else { return FALSE; } } else { if ( !Value.GetVectorValueInteger(i, i64Value) ) { return FALSE; } aBOOL[i] = (VARIANT_BOOL) i64Value != VARIANT_FALSE; } } propVariant.cabool.cElems = size; propVariant.cabool.pElems = aBOOL.Acquire(); } break; case VT_DATE | VT_VECTOR: { // // Dates are in the format YYYY/MM/DD hh:mm:ss:ii // if ( Value.GetType() != (VT_LPWSTR | VT_VECTOR) ) { return FALSE; } XCoMem aDate( size ); for (unsigned i=0; icalpwstr.pElems[i], stUTC ) ) { return FALSE; } if ( !SystemTimeToVariantTime( &stUTC, &aDate[i] ) ) { return FALSE; } } propVariant.cadate.cElems = size; propVariant.cadate.pElems = aDate.Acquire(); } break; case VT_FILETIME | VT_VECTOR: { // // FileTimes are in the format YYYY/MM/DD hh:mm:ss:ii // if ( Value.GetType() != (VT_LPWSTR | VT_VECTOR) ) { return FALSE; } XCoMem aFileTime( size ); for (unsigned i=0; icalpwstr.pElems[i], aFileTime[i] ) ) { return FALSE; } } propVariant.cafiletime.cElems = size; propVariant.cafiletime.pElems = aFileTime.Acquire(); } break; case VT_CY | VT_VECTOR: { XCoMem acy( size ); for (unsigned i=0; ivt) { case VT_UI1: return (double)pVariant->bVal; break; case VT_I1: return (double)(char)pVariant->bVal; break; case VT_UI2: return (double)pVariant->uiVal; break; case VT_I2: return (double)pVariant->iVal; break; case VT_UI4: case VT_UINT: return (double)pVariant->ulVal; break; case VT_I4: case VT_INT: case VT_ERROR: return (double)pVariant->lVal; break; case VT_UI8: // // hVal used instead of uhVal because latter coercion // is not yet supported by x86 compiler. // return (double)pVariant->hVal.QuadPart; break; case VT_I8: return (double) pVariant->hVal.QuadPart; break; case VT_R4: return (double)pVariant->fltVal; break; case VT_R8: return pVariant->dblVal; break; case VT_BOOL: return (double)( VARIANT_FALSE != pVariant->boolVal ); break; case VT_DATE: return (double) pVariant->date; break; case VT_CY: { double dblValue; VarR8FromCy( pVariant->cyVal, &dblValue ); return dblValue; } case VT_DECIMAL: { double dblValue; VarR8FromDec( & pVariant->decVal, &dblValue ); return dblValue; } break; default: Win4Assert( !"VT_TYPE not supported in GetDoubleFromVariant" ); break; } return 0.0; } //+--------------------------------------------------------------------------- // // Function: GetI64FromVariant - static // // Synopsis: Converts a numerical value in a variant to a _int64 // // History: 96/Jan/03 DwightKr created // //---------------------------------------------------------------------------- static _int64 GetI64FromVariant( PROPVARIANT * pVariant ) { switch (pVariant->vt) { case VT_UI1: return (_int64)pVariant->bVal; break; case VT_I1: return (_int64)pVariant->bVal; break; case VT_UI2: return (_int64)pVariant->uiVal; break; case VT_I2: return (_int64)pVariant->iVal; break; case VT_UI4: case VT_UINT: return (_int64)pVariant->ulVal; break; case VT_I4: case VT_INT: case VT_ERROR: return (_int64)pVariant->lVal; break; case VT_UI8: return (_int64)pVariant->uhVal.QuadPart; break; case VT_I8: return pVariant->hVal.QuadPart; break; case VT_R4: Win4Assert( !"VT_R4 not supported in GetI64FromVariant, use GetDoubleFromVariant" ); break; case VT_R8: Win4Assert( !"VT_R8 not supported in GetI64FromVariant, use GetDoubleFromVariant" ); break; case VT_DECIMAL: Win4Assert( !"VT_DECIMAL not supported in GetI64FromVariant, use GetDoubleFromVariant" ); break; case VT_DATE: { LONG lValue; VarI4FromDate( pVariant->date, & lValue ); return lValue; } break; case VT_BOOL: return (_int64) ( VARIANT_FALSE != pVariant->boolVal ); break; case VT_CY: { return (_int64) pVariant->cyVal.Hi; } break; default: Win4Assert( !"VT_TYPE not supported in GetI64FromVariant" ); break; } return 0; } //+--------------------------------------------------------------------------- // // Method: CHTXIfExpression::CHTXIfExpression - public constructor // // Synopsis: Builds a CHTXIfExpression object, and determines if // this is an IF expression. // // Arguments: [scanner] - parser containing the line to be parsed // [variableSet] - list of replaceable parameters // // History: 96/Jan/03 DwightKr created // //---------------------------------------------------------------------------- CHTXIfExpression::CHTXIfExpression( CTokenizeString & scanner, CVariableSet & variableSet, COutputFormat & outputFormat ) : _scanner(scanner), _variableSet(variableSet), _outputFormat(outputFormat) { // // The first word better be an 'if' // Win4Assert ( _scanner.LookAhead() == TEXT_TOKEN ); XPtrST wcsIf( _scanner.AcqWord() ); Win4Assert( _wcsicmp(wcsIf.GetPointer(), L"if") == 0 ); _scanner.Accept(); // Skip over the "if" } //+--------------------------------------------------------------------------- // // Method: CHTXIfExpression::Evaluate - public // // Synopsis: Evaluates an IF expression by breaking it up into the // left-side, operator & right-side. // // Returns: TRUE or FALSE - the evaluation of the IF expression // // History: 96/Jan/03 DwightKr created // //---------------------------------------------------------------------------- BOOL CHTXIfExpression::Evaluate() { CHTXIfExpressionValue lhValue( _scanner, _variableSet, _outputFormat ); lhValue.ParseValue(); CHTXIfExpressionOperator ifOperator( _scanner ); ifOperator.ParseOperator(); if ( ifOperator.Operator() != ISEMPTY_TOKEN ) { CHTXIfExpressionValue rhValue( _scanner, _variableSet, _outputFormat ); rhValue.ParseValue(); return ifOperator.Evaluate( lhValue, rhValue ); } else { if ( _scanner.LookAhead() != EOS_TOKEN ) THROW( CHTXException( MSG_CI_HTX_EXPECTING_OPERATOR, 0, 0 ) ); return ifOperator.Evaluate( lhValue ); } } //+--------------------------------------------------------------------------- // // Method: CHTXIfExpressionValue::CHTXIfExpressionValue - public constructor // // Synopsis: Parses one half of an IF expression and determines its value // // Parameters: [scanner] - parser containing the IF to be parsed // [variableSet] - list of replaceable paremeters // // History: 96/Jan/03 DwightKr created // //---------------------------------------------------------------------------- CHTXIfExpressionValue::CHTXIfExpressionValue( CTokenizeString & scanner, CVariableSet & variableSet, COutputFormat & outputFormat) : _scanner(scanner), _variableSet(variableSet), _outputFormat(outputFormat), _wcsStringValue(0), _fOwnVector(FALSE), _fIsConstant(FALSE) { } //+--------------------------------------------------------------------------- //---------------------------------------------------------------------------- CHTXIfExpressionValue::~CHTXIfExpressionValue() { delete _wcsStringValue; if ( _fOwnVector ) { Win4Assert ( ( _propVariant.vt & VT_VECTOR ) != 0 ); if ( _propVariant.vt == ( VT_LPWSTR | VT_VECTOR ) ) { for (unsigned i=0; i<_propVariant.calpwstr.cElems; i++) { delete _propVariant.calpwstr.pElems[i]; } } delete _propVariant.cal.pElems; } } //+--------------------------------------------------------------------------- // // Method: CHTXIfExpressionValue::ParseValue - public // // Synopsis: Parses one side of an IF expression. // // History: 96/Jan/03 DwightKr created // 96/Feb/13 DwightKr add suppport for quoted strings // //---------------------------------------------------------------------------- void CHTXIfExpressionValue::ParseValue() { // // The first token on this line must be a word/phrase, and not an // operator. It may be quoted. // _fIsConstant = TRUE; // Assume it is a constant, not a var if ( _scanner.LookAhead() == QUOTES_TOKEN ) { _scanner.AcceptQuote(); // Skip over the opening " _propVariant.vt = VT_LPWSTR; _wcsStringValue = _scanner.AcqPhrase(); _scanner.Accept(); // Skip over the string if ( _scanner.LookAhead() != QUOTES_TOKEN ) { THROW( CHTXException(MSG_CI_HTX_MISSING_QUOTE, 0, 0) ); } _scanner.Accept(); // Skip over the closing " } else if (_scanner.LookAhead() == C_OPEN_TOKEN ) { _scanner.Accept(); // Skip over the opening { _scanner.AcqVector( _propVariant ); _fOwnVector = TRUE; if ( _scanner.LookAhead() != C_CLOSE_TOKEN ) { THROW( CHTXException(MSG_CI_HTX_MISSING_BRACKET, 0, 0) ); } _scanner.Accept(); // Skip over the closing } } else { if ( _scanner.LookAhead() != TEXT_TOKEN ) { THROW( CHTXException(QPARSE_E_UNEXPECTED_EOS, 0, 0) ); } // // Determine if this is a number, or a string. If it is a string, // then look it up in the variableSet. If it's defined in the // variableSet, look up its value, and determine if this new value // is a number. // if ( _scanner.GetGUID( _guid ) ) { _propVariant.vt = VT_CLSID; _propVariant.puuid = &_guid; } else if ( _scanner.GetNumber( (unsigned _int64) *((unsigned _int64 *) (&_propVariant.uhVal)) ) ) { _propVariant.vt = VT_UI8; } else if ( _scanner.GetNumber( (_int64) *((_int64 *) (&_propVariant.hVal)) ) ) { _propVariant.vt = VT_I8; } else if ( _scanner.GetNumber( _propVariant.dblVal ) ) { _propVariant.vt = VT_R8; } else { // // Its not a number, get its value in a local buffer. // _propVariant.vt = VT_LPWSTR; XPtrST wcsVariableName( _scanner.AcqWord() ); // // Try to find this variable/string in the variableSet // CVariable *pVariable = _variableSet.Find( wcsVariableName.GetPointer() ); if ( 0 != pVariable ) { _fIsConstant = FALSE; // // We have a variable with this name. Get its string value. // ULONG cwcValue; WCHAR * wcsValue = pVariable->GetStringValueRAW(_outputFormat, cwcValue); _wcsStringValue = new WCHAR[ cwcValue + 1 ]; RtlCopyMemory( _wcsStringValue, wcsValue, (cwcValue+1) * sizeof(WCHAR) ); _propVariant = *pVariable->GetValue(); } else { // // The variable name could not be found. // _wcsStringValue = wcsVariableName.Acquire(); } } _scanner.Accept(); // Skip over the "value" } } //+--------------------------------------------------------------------------- // // Method: CHTXIfExpressionValue::GetStringValue - public // // Synopsis: Returns the string value of the variable // // History: 96/Jan/03 DwightKr created // //---------------------------------------------------------------------------- WCHAR * CHTXIfExpressionValue::GetStringValue() { if ( 0 == _wcsStringValue ) { switch ( _propVariant.vt ) { case VT_I4: _wcsStringValue = new WCHAR[20]; _itow( _propVariant.ulVal, _wcsStringValue, 10 ); break; case VT_UI4: _wcsStringValue = new WCHAR[20]; _itow( _propVariant.lVal, _wcsStringValue, 10 ); break; case VT_R8: _wcsStringValue = new WCHAR[ maxFloatSize ]; swprintf( _wcsStringValue, L"%f", _propVariant.dblVal ); break; default: _wcsStringValue = new WCHAR[1]; _wcsStringValue[0] = 0; break; } } return _wcsStringValue; } //+--------------------------------------------------------------------------- // // Method: CHTXIfExpressionOperator::CHTXIfExpressionOperator - public constructor // // Synopsis: Parses the operator in an IF expression // // Parameters: [scanner] - parser containing the operator to be parsed // // History: 96/Jan/03 DwightKr created // //---------------------------------------------------------------------------- CHTXIfExpressionOperator::CHTXIfExpressionOperator( CTokenizeString & scanner ) : _scanner(scanner), _operator(EQUAL_TOKEN) { } //+--------------------------------------------------------------------------- // // Method: CHTXIfExpressionOperator::ParseOperator - public // // Synopsis: Parses the operator in an IF expression // // History: 96/Jan/03 DwightKr created // //---------------------------------------------------------------------------- void CHTXIfExpressionOperator::ParseOperator() { // // The first token on this line must be a word, and not an operator. // We're looking for operators such as eq, ne, gt, ... // if ( _scanner.LookAhead() != TEXT_TOKEN ) { THROW( CHTXException(MSG_CI_HTX_EXPECTING_OPERATOR, 0, 0) ); } XPtrST wcsOperator( _scanner.AcqWord() ); if ( 0 == wcsOperator.GetPointer() ) THROW( CHTXException(MSG_CI_HTX_EXPECTING_OPERATOR, 0, 0) ); if ( wcscmp(wcsOperator.GetPointer(), L"EQ") == 0 ) { _operator = EQUAL_TOKEN; } else if ( wcscmp(wcsOperator.GetPointer(), L"NE") == 0 ) { _operator = NOT_EQUAL_TOKEN; } else if ( wcscmp(wcsOperator.GetPointer(), L"GT") == 0 ) { _operator = GREATER_TOKEN; } else if ( wcscmp(wcsOperator.GetPointer(), L"GE") == 0 ) { _operator = GREATER_EQUAL_TOKEN; } else if ( wcscmp(wcsOperator.GetPointer(), L"LT") == 0 ) { _operator = LESS_TOKEN; } else if ( wcscmp(wcsOperator.GetPointer(), L"LE") == 0 ) { _operator = LESS_EQUAL_TOKEN; } else if ( wcscmp(wcsOperator.GetPointer(), L"CONTAINS") == 0 ) { _operator = CONTAINS_TOKEN; } else if ( wcscmp(wcsOperator.GetPointer(), L"ISEMPTY") == 0 ) { _operator = ISEMPTY_TOKEN; } else if ( wcscmp(wcsOperator.GetPointer(), L"ISTYPEEQ") == 0 ) { _operator = ISTYPEEQUAL_TOKEN; } else { THROW( CHTXException(MSG_CI_HTX_EXPECTING_OPERATOR, 0, 0) ); } _scanner.Accept(); // Skip over the "operator" } //+--------------------------------------------------------------------------- // // Method: CHTXIfExpressionOperator::Evaluate - public // // Synopsis: Using the operator already obtained, it evaluates a TRUE/FALSE // result by comparing the lhValue and the rhValue. // // Arguments: [lhValue] - left hand value of the IF statement // [rhValue] - right hand value of the IF statement // // History: 96/Jan/03 DwightKr created // //---------------------------------------------------------------------------- BOOL CHTXIfExpressionOperator::Evaluate( CHTXIfExpressionValue & lhValue, CHTXIfExpressionValue & rhValue ) { // // If the operator is CONTAINS_TOKEN, then we'll simply do a wcsistr // of the string representations of the two values. // if ( CONTAINS_TOKEN == _operator ) { return wcsistr(lhValue.GetStringValue(), rhValue.GetStringValue()) != 0; } // // We must setup the comparision functions to examine like types. // The type of lhValue and rhValue must be converted to like types. // If any one of them is a string, then we'll treat both of them // like strings. // PROPVARIANT lhVariant; PROPVARIANT rhVariant; SPropVariant xlhPropVariant; SPropVariant xrhPropVariant; // // If neither one are vectors, perform the following conversions // if ( ((lhValue.GetType() & VT_VECTOR) == 0) && ((rhValue.GetType() & VT_VECTOR) == 0) ) { if ( (lhValue.GetType() == VT_LPWSTR) || (rhValue.GetType() == VT_LPWSTR) || (lhValue.GetType() == VT_LPSTR) || (rhValue.GetType() == VT_LPSTR) || (lhValue.GetType() == VT_BSTR) || (rhValue.GetType() == VT_BSTR) ) { lhVariant.vt = VT_LPWSTR; rhVariant.vt = VT_LPWSTR; lhVariant.pwszVal = lhValue.GetStringValue(); rhVariant.pwszVal = rhValue.GetStringValue(); } else if (lhValue.GetType() == rhValue.GetType() || lhValue.GetType() == VT_EMPTY || rhValue.GetType() == VT_EMPTY) { lhVariant = *lhValue.GetValue(); rhVariant = *rhValue.GetValue(); } else if ( (lhValue.GetType() == VT_FILETIME) || (rhValue.GetType() == VT_FILETIME) ) { if ( lhValue.GetType() == VT_LPWSTR ) { if ( !StringToFileTime( lhValue.GetValue()->pwszVal, lhVariant.filetime ) ) { return FALSE; } lhVariant.vt = VT_FILETIME; rhVariant = *rhValue.GetValue(); } else if ( rhValue.GetType() == VT_LPWSTR ) { if ( !StringToFileTime( rhValue.GetValue()->pwszVal, rhVariant.filetime ) ) { return FALSE; } rhVariant.vt = VT_FILETIME; lhVariant = *lhValue.GetValue(); } } else if ( (lhValue.GetType() == VT_R4) || (lhValue.GetType() == VT_R8) || (rhValue.GetType() == VT_R4) || (rhValue.GetType() == VT_R8) || (lhValue.GetType() == VT_CY) || (rhValue.GetType() == VT_CY) || (lhValue.GetType() == VT_DECIMAL) || (rhValue.GetType() == VT_DECIMAL) || (lhValue.GetType() == VT_DATE) || (rhValue.GetType() == VT_DATE) ) { // // At least one of them is a floating number. Convert them both // to floating point. // lhVariant.vt = VT_R8; rhVariant.vt = VT_R8; lhVariant.dblVal = GetDoubleFromVariant( lhValue.GetValue() ); rhVariant.dblVal = GetDoubleFromVariant( rhValue.GetValue() ); } else if ( (lhValue.GetType() == VT_I8) || (lhValue.GetType() == VT_I4) || (lhValue.GetType() == VT_I2) || (lhValue.GetType() == VT_I1) || (rhValue.GetType() == VT_I8) || (rhValue.GetType() == VT_I4) || (rhValue.GetType() == VT_I2) || (rhValue.GetType() == VT_I1) || (lhValue.GetType() == VT_INT) || (rhValue.GetType() == VT_INT) ) { lhVariant.vt = VT_I8; rhVariant.vt = VT_I8; lhVariant.hVal.QuadPart = GetI64FromVariant( lhValue.GetValue() ); rhVariant.hVal.QuadPart = GetI64FromVariant( rhValue.GetValue() ); } else if ( (lhValue.GetType() == VT_UI8) || (lhValue.GetType() == VT_UI4) || (lhValue.GetType() == VT_UI2) || (lhValue.GetType() == VT_UI1) || (rhValue.GetType() == VT_UI8) || (rhValue.GetType() == VT_UI4) || (rhValue.GetType() == VT_UI2) || (rhValue.GetType() == VT_UI1) || (lhValue.GetType() == VT_UINT) || (rhValue.GetType() == VT_UINT) ) { lhVariant.vt = VT_UI8; rhVariant.vt = VT_UI8; lhVariant.uhVal.QuadPart = GetI64FromVariant( lhValue.GetValue() ); rhVariant.uhVal.QuadPart = GetI64FromVariant( rhValue.GetValue() ); } else { lhVariant = *lhValue.GetValue(); rhVariant = *rhValue.GetValue(); } } else if ( ((lhValue.GetType() & VT_VECTOR) != 0) && ((rhValue.GetType() & VT_VECTOR) != 0) ) { // // Both are vectors // // // If the vector's are of different types, attempt to Coerce one // type into the other. // if ( lhValue.GetType() != rhValue.GetType() ) { // // Coerce the types to be the same if possible. Attempt to // Coerce a constant into the type of the variable, rather // then vise versa. If this fails, attempt the opposite // coearison. // if ( lhValue.IsConstant() ) { if ( VectorCoerce( lhValue, rhValue.GetType(), lhVariant ) ) { Win4Assert( xlhPropVariant.IsNull() ); xlhPropVariant.Set( &lhVariant ); rhVariant = *rhValue.GetValue(); } else { if ( VectorCoerce( rhValue, lhValue.GetType(), rhVariant ) ) { Win4Assert( xrhPropVariant.IsNull() ); xrhPropVariant.Set( &rhVariant ); lhVariant = *lhValue.GetValue(); } } } else if ( rhValue.IsConstant() ) { if ( VectorCoerce( rhValue, lhValue.GetType(), rhVariant ) ) { Win4Assert( xrhPropVariant.IsNull() ); xrhPropVariant.Set( &rhVariant ); lhVariant = *lhValue.GetValue(); } else { if ( VectorCoerce( lhValue, rhValue.GetType(), lhVariant ) ) { Win4Assert( xlhPropVariant.IsNull() ); xlhPropVariant.Set( &lhVariant ); rhVariant = *rhValue.GetValue(); } } } else { lhVariant = *lhValue.GetValue(); rhVariant = *rhValue.GetValue(); } } else { lhVariant = *lhValue.GetValue(); rhVariant = *rhValue.GetValue(); } } else { lhVariant = *lhValue.GetValue(); rhVariant = *rhValue.GetValue(); } switch ( _operator ) { case EQUAL_TOKEN: return VT_VARIANT_EQ( lhVariant, rhVariant ); break; case NOT_EQUAL_TOKEN: return VT_VARIANT_NE( lhVariant, rhVariant ); break; case GREATER_TOKEN: return VT_VARIANT_GT( lhVariant, rhVariant ); break; case GREATER_EQUAL_TOKEN: return VT_VARIANT_GE( lhVariant, rhVariant ); break; case LESS_TOKEN: return VT_VARIANT_LT( lhVariant, rhVariant ); break; case LESS_EQUAL_TOKEN: return VT_VARIANT_LE( lhVariant, rhVariant ); break; case ISTYPEEQUAL_TOKEN: { // // Three valid cases exist: // // if variable IsTypeEQ constant // if constant IsTypeEQ variable // if variable IsTypeEQ variable // // Therefore, at least ONE of them must be a variable. // if ( lhValue.IsConstant() && rhValue.IsConstant() ) { THROW( CHTXException(MSG_CI_HTX_ISTYPEEQUAL_WITH_CONSTANTS, 0, 0) ); } // // If a constant is used, then it must be of type I4. Not floating, // guid, vector, etc. // if ( lhValue.IsConstant() ) { if ( lhValue.GetType() != VT_UI4 ) { THROW( CHTXException(MSG_CI_HTX_ISTYPEEQUAL_INVALID_CONSTANT, 0, 0) ); } return lhValue.GetValue()->ulVal == (ULONG) rhValue.GetType(); } else if ( rhValue.IsConstant() ) { if ( rhValue.GetType() != VT_UI4 ) { THROW( CHTXException(MSG_CI_HTX_ISTYPEEQUAL_INVALID_CONSTANT, 0, 0) ); } return rhValue.GetValue()->ulVal == (ULONG) lhValue.GetType(); } else { return lhValue.GetType() == rhValue.GetType(); } } break; default: Win4Assert(!"Illegal case in NON-VECTOR CExpressionOperator::Evaluate" ); return FALSE; break; } return FALSE; } //+--------------------------------------------------------------------------- // // Method: CHTXIfExpressionOperator::Evaluate - public // // Synopsis: Using the operator already obtained, it evaluates a TRUE/FALSE // result by comparing the lhValue and the rhValue. // // Arguments: [lhValue] - left hand value of the IF statement // // History: 29-Jun-96 KyleP created // //---------------------------------------------------------------------------- BOOL CHTXIfExpressionOperator::Evaluate( CHTXIfExpressionValue & lhValue ) { Win4Assert( ISEMPTY_TOKEN == _operator ); BOOL fEmpty; ULONG vt = lhValue.GetType(); switch ( vt ) { case VT_EMPTY: case VT_NULL: fEmpty = TRUE; break; case VT_LPSTR: { char const * pszVal = lhValue.GetValue()->pszVal; unsigned cc = strlen( pszVal ); fEmpty = IsEmpty( pszVal, cc ); break; } case VT_LPSTR | VT_VECTOR: { for ( unsigned i = 0; i < lhValue.GetValue()->calpstr.cElems; i++ ) { char const * pszVal = lhValue.GetValue()->calpstr.pElems[i]; unsigned cc = strlen( pszVal ); fEmpty = IsEmpty( pszVal, cc ); if ( !fEmpty ) break; } break; } case VT_BSTR: { WCHAR const * pwszVal = lhValue.GetValue()->bstrVal; unsigned cc = BSTRLEN( lhValue.GetValue()->bstrVal ); fEmpty = IsEmpty( pwszVal, cc ); break; } case VT_BSTR | VT_VECTOR: { for ( unsigned i = 0; i < lhValue.GetValue()->cabstr.cElems; i++ ) { WCHAR const * pwszVal = lhValue.GetValue()->cabstr.pElems[i]; unsigned cc = BSTRLEN( lhValue.GetValue()->cabstr.pElems[i] ); fEmpty = IsEmpty( pwszVal, cc ); if ( !fEmpty ) break; } break; } case VT_LPWSTR: { WCHAR const * pwszVal = lhValue.GetValue()->pwszVal; unsigned cc = wcslen( pwszVal ); fEmpty = IsEmpty( pwszVal, cc ); break; } case VT_LPWSTR | VT_VECTOR: { for ( unsigned i = 0; i < lhValue.GetValue()->calpwstr.cElems; i++ ) { WCHAR const * pwszVal = lhValue.GetValue()->calpwstr.pElems[i]; unsigned cc = wcslen( pwszVal ); fEmpty = IsEmpty( pwszVal, cc ); if ( !fEmpty ) break; } break; } default: fEmpty = FALSE; } return fEmpty; } //+--------------------------------------------------------------------------- // // Method: CHTXIfExpressionValue::GetVectorValueInteger, public // // Synopsis: Returns the _int64 value of a vector's element // // History: 96/Jun/27 DwightKr created // //---------------------------------------------------------------------------- BOOL CHTXIfExpressionValue::GetVectorValueInteger( unsigned index, _int64 & i64Value ) { switch ( GetType() ) { case VT_UI1 | VT_VECTOR: i64Value = (_int64) _propVariant.caub.pElems[index]; break; case VT_I1 | VT_VECTOR: i64Value = (_int64) _propVariant.caub.pElems[index]; break; case VT_UI2 | VT_VECTOR: i64Value = (_int64) _propVariant.caui.pElems[index]; break; case VT_I2 | VT_VECTOR: i64Value = (_int64) _propVariant.cai.pElems[index]; break; case VT_UI4 | VT_VECTOR: i64Value = (_int64) _propVariant.caul.pElems[index]; break; case VT_I4 | VT_VECTOR: i64Value = (_int64) _propVariant.cal.pElems[index]; break; case VT_UI8 | VT_VECTOR: i64Value = (_int64) _propVariant.cauh.pElems[index].QuadPart; break; case VT_I8 | VT_VECTOR: i64Value = (_int64) _propVariant.cah.pElems[index].QuadPart; break; case VT_R4 | VT_VECTOR: return FALSE; break; case VT_R8 | VT_VECTOR: return FALSE; break; case VT_DATE | VT_VECTOR: { LONG lValue; VarI4FromDate( _propVariant.cadate.pElems[index], &lValue ); i64Value = lValue; } break; case VT_BOOL | VT_VECTOR: i64Value = (_int64) ( VARIANT_FALSE != _propVariant.cabool.pElems[index] ); break; case VT_CY | VT_VECTOR: { return FALSE; } break; default: return FALSE; break; } return TRUE; } //+--------------------------------------------------------------------------- // // Method: CHTXIfExpressionValue::GetVectorValueUnsignedInteger, public // // Synopsis: Returns the unsigned _int64 value of a vector's element // // History: 96/Jun/27 DwightKr created // //---------------------------------------------------------------------------- BOOL CHTXIfExpressionValue::GetVectorValueUnsignedInteger( unsigned index, unsigned _int64 & ui64Value ) { switch ( GetType() ) { case VT_UI1 | VT_VECTOR: ui64Value = (unsigned _int64) _propVariant.caub.pElems[index]; break; case VT_I1 | VT_VECTOR: if ( _propVariant.cac.pElems[index] < 0 ) return FALSE; ui64Value = (unsigned _int64) _propVariant.cac.pElems[index]; break; case VT_UI2 | VT_VECTOR: ui64Value = (unsigned _int64) _propVariant.caui.pElems[index]; break; case VT_I2 | VT_VECTOR: if ( _propVariant.cai.pElems[index] < 0 ) return FALSE; ui64Value = (unsigned _int64) _propVariant.cai.pElems[index]; break; case VT_UI4 | VT_VECTOR: ui64Value = (unsigned _int64) _propVariant.caul.pElems[index]; break; case VT_I4 | VT_VECTOR: if ( _propVariant.cal.pElems[index] < 0 ) return FALSE; ui64Value = (unsigned _int64) _propVariant.cal.pElems[index]; break; case VT_UI8 | VT_VECTOR: ui64Value = (unsigned _int64) _propVariant.cauh.pElems[index].QuadPart; break; case VT_I8 | VT_VECTOR: if ( _propVariant.cah.pElems[index].QuadPart < 0 ) return FALSE; ui64Value = (unsigned _int64) _propVariant.cah.pElems[index].QuadPart; break; case VT_R4 | VT_VECTOR: return FALSE; break; case VT_R8 | VT_VECTOR: return FALSE; break; case VT_BOOL | VT_VECTOR: ui64Value = (unsigned _int64) ( VARIANT_FALSE != _propVariant.cabool.pElems[index] ); break; case VT_CY | VT_VECTOR: { return FALSE; } break; default: return FALSE; break; } return TRUE; } //+--------------------------------------------------------------------------- // // Method: CHTXIfExpressionValue::GetVectorValueDouble, public // // Synopsis: Returns the double value of a vector's element // // History: 96/Jun/27 DwightKr created // //---------------------------------------------------------------------------- BOOL CHTXIfExpressionValue::GetVectorValueDouble(unsigned index, double & dblValue) { switch ( GetType() ) { case VT_UI1 | VT_VECTOR: VarR8FromUI1( _propVariant.caub.pElems[index], &dblValue ); break; case VT_I1 | VT_VECTOR: VarR8FromI1( _propVariant.caub.pElems[index], &dblValue ); break; case VT_UI2 | VT_VECTOR: VarR8FromUI2( _propVariant.caui.pElems[index], &dblValue ); break; case VT_I2 | VT_VECTOR: VarR8FromI2( _propVariant.cai.pElems[index], &dblValue ); break; case VT_UI4 | VT_VECTOR: VarR8FromUI4( _propVariant.caul.pElems[index], &dblValue ); break; case VT_I4 | VT_VECTOR: VarR8FromI4( _propVariant.cal.pElems[index], &dblValue ); break; case VT_UI8 | VT_VECTOR: dblValue = (double) _propVariant.cah.pElems[index].QuadPart; break; case VT_I8 | VT_VECTOR: // // hVal used instead of uhVal because latter coercion // is not yet supported by x86 compiler. // dblValue = (double) _propVariant.cah.pElems[index].QuadPart; break; case VT_R4 | VT_VECTOR: VarR8FromR4( _propVariant.caflt.pElems[index], &dblValue ); break; case VT_R8 | VT_VECTOR: dblValue = (double) _propVariant.cadbl.pElems[index]; break; case VT_DATE | VT_VECTOR: VarR8FromDate( _propVariant.cadate.pElems[index], &dblValue ); break; case VT_BOOL | VT_VECTOR: VarR8FromBool( _propVariant.cabool.pElems[index], &dblValue ); break; case VT_CY | VT_VECTOR: VarR8FromCy( _propVariant.cacy.pElems[index], &dblValue ); break; default: return FALSE; break; } return TRUE; } //+--------------------------------------------------------------------------- // // Method: CHTXIfExpressionValue::GetVectorValueWStr, public // // Synopsis: Returns the wide string representation of a vector's element // in OLE memory. // // History: 96/Jun/27 DwightKr created // //---------------------------------------------------------------------------- BOOL CHTXIfExpressionValue::GetVectorValueWStr(unsigned index, XCoMem & wcsStringValue ) { switch ( GetType() ) { case VT_BSTR | VT_VECTOR: case VT_LPWSTR | VT_VECTOR: { unsigned cwcStringValue; if ( GetType() == (VT_LPWSTR | VT_VECTOR) ) { cwcStringValue = wcslen( _propVariant.calpwstr.pElems[index] ) + 1; } else { cwcStringValue = BSTRLEN( _propVariant.cabstr.pElems[index] ) + 1; } wcsStringValue.Init( cwcStringValue ); RtlCopyMemory( wcsStringValue.GetPointer(), _propVariant.calpwstr.pElems[index], cwcStringValue * sizeof(WCHAR) ); } break; case VT_LPSTR | VT_VECTOR: { XArray wcsBuffer; ULONG cbBuffer = strlen(_propVariant.calpstr.pElems[index]) + 1; ULONG cwcBuffer = MultiByteToXArrayWideChar( (UCHAR const *) _propVariant.calpstr.pElems[index], cbBuffer, _outputFormat.CodePage(), wcsBuffer ); if ( 0 == cwcBuffer ) { return FALSE; } wcsStringValue.Init( cwcBuffer + 1 ); RtlCopyMemory( wcsStringValue.GetPointer(), wcsBuffer.GetPointer(), (cwcBuffer+1) * sizeof(WCHAR) ); } break; default: return FALSE; break; } return TRUE; } //+--------------------------------------------------------------------------- // // Method: CHTXIfExpressionValue::GetVectorValueStr, public // // Synopsis: Returns the string representation of a vector's element // in OLE memory. // // History: 96/Jun/27 DwightKr created // //---------------------------------------------------------------------------- BOOL CHTXIfExpressionValue::GetVectorValueStr(unsigned index, XCoMem & pszStringValue ) { XCoMem wcsStringValue; if ( !GetVectorValueWStr( index, wcsStringValue ) ) { return FALSE; } ULONG cwcBuffer = wcslen( wcsStringValue.GetPointer() ) + 1; XArray pszMessage(cwcBuffer); ULONG cbBuffer = WideCharToXArrayMultiByte( wcsStringValue.GetPointer(), cwcBuffer, _outputFormat.CodePage(), pszMessage ); if ( 0 == cbBuffer ) { return FALSE; } pszStringValue.Init( cbBuffer + 1 ); RtlCopyMemory( pszStringValue.GetPointer(), pszMessage.GetPointer(), cbBuffer + 1 ); return TRUE; } //+--------------------------------------------------------------------------- // // Method: CHTXIfExpressionValue::GetVectorValueBStr, public // // Synopsis: Returns the B string representation of a vector's element // in OLE memory. // // History: 96/Jun/27 DwightKr created // //---------------------------------------------------------------------------- BOOL CHTXIfExpressionValue::GetVectorValueBStr(unsigned index, BSTR & bwszStringValue ) { XCoMem wszStringValue; if ( !GetVectorValueWStr(index, wszStringValue) ) { return FALSE; } bwszStringValue = SysAllocString( wszStringValue.GetPointer() ); if ( 0 == bwszStringValue ) { THROW ( CException( E_OUTOFMEMORY ) ); } return TRUE; }