1964 lines
53 KiB
C++
1964 lines
53 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// 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 <pch.cxx>
|
|
#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<PCHAR> aStr( size );
|
|
for (unsigned i=0; i<size; i++)
|
|
{
|
|
XCoMem<CHAR> 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<PWCHAR> aWStr( size );
|
|
for (unsigned i=0; i<size; i++)
|
|
{
|
|
XCoMem<WCHAR> 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<BSTR> aBStr( size );
|
|
for (unsigned i=0; i<size; i++)
|
|
{
|
|
BSTR bwszStringValue;
|
|
if ( !Value.GetVectorValueBStr(i, bwszStringValue) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
aBStr[i] = bwszStringValue;
|
|
}
|
|
|
|
propVariant.cabstr.cElems = size;
|
|
propVariant.cabstr.pElems = aBStr.Acquire();
|
|
}
|
|
break;
|
|
|
|
case VT_UI1 | VT_VECTOR:
|
|
{
|
|
XCoMem<BYTE> aUI1( size );
|
|
for (unsigned i=0; i<size; i++)
|
|
{
|
|
if ( !Value.GetVectorValueUnsignedInteger(i, ui64Value) ||
|
|
ui64Value > UCHAR_MAX )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
aUI1[i] = (BYTE) ui64Value;
|
|
}
|
|
|
|
propVariant.caub.cElems = size;
|
|
propVariant.caub.pElems = aUI1.Acquire();
|
|
}
|
|
break;
|
|
|
|
case VT_I1 | VT_VECTOR:
|
|
{
|
|
XCoMem<BYTE> aI1( size );
|
|
for (unsigned i=0; i<size; i++)
|
|
{
|
|
if ( !Value.GetVectorValueInteger(i, i64Value) ||
|
|
(i64Value < SCHAR_MIN) || (i64Value > SCHAR_MAX) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
aI1[i] = (BYTE) i64Value;
|
|
}
|
|
|
|
propVariant.caub.cElems = size;
|
|
propVariant.caub.pElems = aI1.Acquire();
|
|
}
|
|
break;
|
|
|
|
case VT_UI2 | VT_VECTOR:
|
|
{
|
|
XCoMem<USHORT> aUI2( size );
|
|
for (unsigned i=0; i<size; i++)
|
|
{
|
|
if ( !Value.GetVectorValueUnsignedInteger(i, ui64Value) ||
|
|
(ui64Value > 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<SHORT> aI2( size );
|
|
for (unsigned i=0; i<size; i++)
|
|
{
|
|
if ( !Value.GetVectorValueInteger(i, i64Value) ||
|
|
(i64Value < SHRT_MIN)|| (i64Value > SHRT_MAX) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
aI2[i] = (SHORT) i64Value;
|
|
}
|
|
|
|
propVariant.cai.cElems = size;
|
|
propVariant.cai.pElems = aI2.Acquire();
|
|
}
|
|
break;
|
|
|
|
case VT_UI4 | VT_VECTOR:
|
|
{
|
|
XCoMem<ULONG> aUI4( size );
|
|
for (unsigned i=0; i<size; i++)
|
|
{
|
|
if ( !Value.GetVectorValueUnsignedInteger(i, ui64Value) ||
|
|
(ui64Value > ULONG_MAX) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
aUI4[i] = (ULONG) ui64Value;
|
|
}
|
|
|
|
propVariant.caul.cElems = size;
|
|
propVariant.caul.pElems = aUI4.Acquire();
|
|
}
|
|
break;
|
|
|
|
case VT_I4 | VT_VECTOR:
|
|
{
|
|
XCoMem<LONG> aI4( size );
|
|
for (unsigned i=0; i<size; i++)
|
|
{
|
|
if ( !Value.GetVectorValueInteger(i, i64Value) ||
|
|
(i64Value < LONG_MIN) || (i64Value > 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<LARGE_INTEGER> aUI8( size );
|
|
for (unsigned i=0; i<size; i++)
|
|
{
|
|
if ( !Value.GetVectorValueInteger(i, i64Value) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
aUI8[i].QuadPart = i64Value;
|
|
}
|
|
|
|
propVariant.cah.cElems = size;
|
|
propVariant.cah.pElems = aUI8.Acquire();
|
|
}
|
|
break;
|
|
|
|
case VT_R4 | VT_VECTOR:
|
|
{
|
|
XCoMem<float> aR4( size );
|
|
for (unsigned i=0; i<size; i++)
|
|
{
|
|
if ( !Value.GetVectorValueDouble(i, dblValue) ||
|
|
(dblValue < -FLT_MAX) || (dblValue > FLT_MAX) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
aR4[i] = (float) dblValue;
|
|
}
|
|
|
|
propVariant.caflt.cElems = size;
|
|
propVariant.caflt.pElems = aR4.Acquire();
|
|
}
|
|
break;
|
|
|
|
case VT_R8 | VT_VECTOR:
|
|
{
|
|
XCoMem<double> aR8( size );
|
|
for (unsigned i=0; i<size; i++)
|
|
{
|
|
if ( !Value.GetVectorValueDouble(i, dblValue) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
aR8[i] = (double) dblValue;
|
|
}
|
|
|
|
propVariant.cadbl.cElems = size;
|
|
propVariant.cadbl.pElems = aR8.Acquire();
|
|
}
|
|
break;
|
|
|
|
case VT_BOOL | VT_VECTOR:
|
|
{
|
|
XCoMem<VARIANT_BOOL> aBOOL( size );
|
|
for (unsigned i=0; i<size; i++)
|
|
{
|
|
if ( Value.GetType() == (VT_LPWSTR | VT_VECTOR) )
|
|
{
|
|
if ( (_wcsicmp(Value.GetValue()->calpwstr.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<DATE> aDate( size );
|
|
for (unsigned i=0; i<size; i++)
|
|
{
|
|
SYSTEMTIME stUTC;
|
|
|
|
if ( !StringToSystemTime( Value.GetValue()->calpwstr.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<FILETIME> aFileTime( size );
|
|
for (unsigned i=0; i<size; i++)
|
|
{
|
|
SYSTEMTIME stUTC;
|
|
|
|
if ( !StringToFileTime( Value.GetValue()->calpwstr.pElems[i],
|
|
aFileTime[i] )
|
|
)
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
propVariant.cafiletime.cElems = size;
|
|
propVariant.cafiletime.pElems = aFileTime.Acquire();
|
|
}
|
|
break;
|
|
|
|
case VT_CY | VT_VECTOR:
|
|
{
|
|
XCoMem<CY> acy( size );
|
|
for (unsigned i=0; i<size; i++)
|
|
{
|
|
if ( !Value.GetVectorValueDouble(i, dblValue) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
VarCyFromR8( dblValue, &acy[i] );
|
|
}
|
|
|
|
propVariant.cacy.cElems = size;
|
|
propVariant.cacy.pElems = acy.Acquire();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
break;
|
|
}
|
|
|
|
propVariant.vt = type;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: wcsistr
|
|
//
|
|
// Synopsis: A case-insensitive, WCHAR implemtation or strstr.
|
|
//
|
|
// Arguments: [wcsString] - string to search
|
|
// [wcsPattern] - pattern to look for
|
|
//
|
|
// Returns; pointer to pattern, 0 if no match found.
|
|
//
|
|
// History: 96/Mar/12 DwightKr created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
static WCHAR const * wcsistr( WCHAR const * wcsString, WCHAR const * wcsPattern )
|
|
{
|
|
if ( (wcsPattern == 0) || (*wcsPattern == 0) )
|
|
{
|
|
return wcsString;
|
|
}
|
|
|
|
ULONG cwcPattern = wcslen(wcsPattern);
|
|
|
|
while ( *wcsString != 0 )
|
|
{
|
|
while ( (*wcsString != 0) &&
|
|
(towupper(*wcsString) != towupper(*wcsPattern))
|
|
)
|
|
{
|
|
wcsString++;
|
|
}
|
|
|
|
if ( 0 == *wcsString )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if ( _wcsnicmp( wcsString, wcsPattern, cwcPattern) == 0 )
|
|
{
|
|
return wcsString;
|
|
}
|
|
|
|
wcsString++;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetDoubleFromVariant - static
|
|
//
|
|
// Synopsis: Converts a numerical value in a variant to a double.
|
|
//
|
|
// History: 96/Jan/03 DwightKr created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
static double GetDoubleFromVariant( PROPVARIANT * pVariant )
|
|
{
|
|
switch (pVariant->vt)
|
|
{
|
|
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<WCHAR> 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<WCHAR> 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[320];
|
|
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<WCHAR> 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:
|
|
ui64Value = (unsigned _int64) _propVariant.caub.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<WCHAR> & 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<WCHAR> 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<CHAR> & pszStringValue )
|
|
{
|
|
XCoMem<WCHAR> wcsStringValue;
|
|
if ( !GetVectorValueWStr( index, wcsStringValue ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
ULONG cwcBuffer = wcslen( wcsStringValue.GetPointer() ) + 1;
|
|
XArray<BYTE> 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<WCHAR> wszStringValue;
|
|
if ( !GetVectorValueWStr(index, wszStringValue) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
bwszStringValue = SysAllocString( wszStringValue.GetPointer() );
|
|
if ( 0 == bwszStringValue )
|
|
{
|
|
THROW ( CException( E_OUTOFMEMORY ) );
|
|
}
|
|
|
|
return TRUE;
|
|
}
|