|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992-2000.
//
// File: variable.cxx
//
// Contents: Used to replace variables
//
// History: 96/Jan/3 DwightKr Created
//
//----------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
void RenderSafeArray( VARTYPE vt, SAFEARRAY * psa, COutputFormat & outputFormat, CVirtualString & vString, BOOL fFormatted );
//+---------------------------------------------------------------------------
//
// Member: CVariable::CVariable - public constructor
//
// Synopsis: Builds a single replaceable variable based in a propVariant
//
// Arguments: [wcsName] - friendly name for the variable
// [pVariant] - the variable's value
// [ulFlags] - all flags associated with this variable, for
// now this indicates if this variable requires
// a IRowsetScroll to access its value.
//
// History: 96/Jan/03 DwightKr Created.
//
//----------------------------------------------------------------------------
CVariable::CVariable( WCHAR const * wcsName, PROPVARIANT const * pVariant, ULONG ulFlags ) : _wcsName(0), _wcsRAWValue(0), _cwcRAWValue(0), _eNumType( eNotANumber ), _ulFlags(ulFlags), _pNext(0), _pBack(0) { Win4Assert( wcsName != 0 );
ULONG cwcName = wcslen(wcsName) + 1; _wcsName = new WCHAR[ cwcName ]; RtlCopyMemory( _wcsName, wcsName, cwcName * sizeof(WCHAR) );
_variant.vt = VT_EMPTY; _variant.pwszVal = 0;
if ( 0 != pVariant ) { // SetValue cannot raise
SetValue( pVariant, ulFlags ); } }
//+---------------------------------------------------------------------------
//
// Member: CVariable::CVariable - public copy constructor
//
// Synopsis: Builds a single replaceable variable based in a propVariant
//
// Arguments: [variable] - the variable to copy
//
// History: 96/Jan/03 DwightKr Created.
//
//----------------------------------------------------------------------------
CVariable::CVariable( const CVariable & variable ) : _wcsName(0), _cwcRAWValue(0), _eNumType( variable._eNumType ), _ulFlags(0), _pNext(0)
{ ULONG cwcName = wcslen(variable._wcsName) + 1;
_wcsName = new WCHAR[ cwcName ];
RtlCopyMemory( _wcsName, variable._wcsName, cwcName * sizeof(WCHAR) );
_ulFlags = variable._ulFlags; _variant = variable._variant;
if ( VT_LPWSTR == variable._variant.vt ) { _cwcRAWValue = variable._cwcRAWValue; } }
//+---------------------------------------------------------------------------
//
// Member: CVariable::~CVariable - public destructor
//
// History: 96/Jan/03 DwightKr Created.
//
//----------------------------------------------------------------------------
CVariable::~CVariable() { if ( (_ulFlags & eParamOwnsVariantMemory) != 0 ) { delete _variant.pwszVal; }
//
// If we have a RAW string that is not part of the variant, and is
// not pointing to the in-line number buffer, delete it. It's probably
// an ASCII string we've converted to WCHAR.
//
if ( _wcsRAWValue && _wcsRAWValue != _wcsNumberValue && _wcsRAWValue != _variant.pwszVal ) { delete _wcsRAWValue; }
delete _wcsName;
if ( 0 != _pNext ) delete _pNext; }
//+---------------------------------------------------------------------------
//
// Member: CVariable::SetValue - public
//
// Synopsis: An assignment operator; allows the value of a variable to
// be changed.
//
// Arguments: [pVariant] - new value for this variable
//
// History: 96/Jan/03 DwightKr Created.
//
//----------------------------------------------------------------------------
void CVariable::SetValue( PROPVARIANT const * pVariant, ULONG ulFlags ) { //
// If we've stored a string equivalent for the old value, then
// delete it now.
//
if ( _wcsRAWValue && _wcsRAWValue != _wcsNumberValue && _wcsRAWValue != _variant.pwszVal ) { delete _wcsRAWValue; _wcsRAWValue = 0; _cwcRAWValue = 0; _eNumType = eNotANumber; }
if ( (_ulFlags & eParamOwnsVariantMemory) != 0 ) { delete _variant.pwszVal; _variant.pwszVal = 0;
_ulFlags &= ~eParamOwnsVariantMemory; }
if ( 0 != pVariant ) _variant = *pVariant; else { _variant.vt = VT_EMPTY; _variant.pwszVal = 0; // retentive
}
//
// If its a WCHAR string, we already have a pointer to its RAW value.
//
if ( (VT_LPWSTR == _variant.vt) && (0 != _variant.pwszVal) ) { _wcsRAWValue = _variant.pwszVal; _cwcRAWValue = wcslen(_wcsRAWValue); } else { _wcsRAWValue = 0; _cwcRAWValue = 0; }
_ulFlags |= ulFlags; }
//+---------------------------------------------------------------------------
//
// Member: CVariable::FastSetValue - public
//
// Synopsis: Special version of SetValue that can be faster because it
// knows that the variable can't own variant memory, that
// the variant is non-0, that the flags are 0, and that variant
// wide strings are non-zero.
//
// Arguments: [pVariant] - new value for this variable
//
// History: 96/Apr/05 dlee Created.
//
//----------------------------------------------------------------------------
void CVariable::FastSetValue( PROPVARIANT const * pVariant ) { //
// If we've stored a string equivalent for the old value, then
// delete it now.
//
if ( ( _wcsRAWValue != _wcsNumberValue ) && ( _wcsRAWValue != _variant.pwszVal ) ) { delete _wcsRAWValue; _wcsRAWValue = 0; _cwcRAWValue = 0; } _eNumType = eNotANumber;
Win4Assert( (_ulFlags & eParamOwnsVariantMemory) == 0 ); Win4Assert( 0 != pVariant ); _variant = *pVariant;
if ( VT_LPWSTR == _variant.vt ) { // The caller of FastSetValue can't pass a 0 string variant
Win4Assert( 0 != _variant.pwszVal ); _wcsRAWValue = _variant.pwszVal; _cwcRAWValue = wcslen(_wcsRAWValue); } else { _wcsRAWValue = 0; _cwcRAWValue = 0; } }
//+---------------------------------------------------------------------------
//
// Member: CVariable::SetValue - public
//
// Synopsis: A assignment operator; allows the value of a variable to
// be changed. Ownership of the string is transferred to this
// function
//
// Arguments: [wcsValue] - new value for this variable
// [cwcValue] - length of new value string
//
// History: 96/Jan/03 DwightKr Created.
//
//----------------------------------------------------------------------------
void CVariable::SetValue( XPtrST<WCHAR> & wcsValue, ULONG cwcValue ) { Win4Assert( VT_LPWSTR == _variant.vt );
//
// If we've stored a string equivalent for the old value, then
// delete it now.
//
if ( _wcsRAWValue && _wcsRAWValue != _wcsNumberValue && _wcsRAWValue != _variant.pwszVal ) { delete _wcsRAWValue; _wcsRAWValue = 0; _cwcRAWValue = 0; _eNumType = eNotANumber; }
if ( (_ulFlags & eParamOwnsVariantMemory) != 0 ) { delete _variant.pwszVal; _variant.pwszVal = 0; }
_ulFlags |= eParamOwnsVariantMemory;
_wcsRAWValue = wcsValue.Acquire(); _cwcRAWValue = cwcValue; }
// Maximum length of a floating point value string
// Big enough for a 1e308 + 9 decimal places + sign + slop
// Floating point precision.
// +1 because the numbers in float.h seem to be too small by one digit.
const unsigned fltPrec = FLT_DIG+1; const unsigned dblPrec = DBL_DIG+1;
//+---------------------------------------------------------------------------
//
// Function: SARenderElementFormatted
//
// Synopsis: Appends the formatted string form a safearray element to
// a virtual string.
// Only the subset of types that are formatted differently
// when "formatted" vs "raw" are handled in this function.
//
// Arguments: [outputFormat] -- The output format to use
// [vString] -- Where the result is appended
// [vt] -- Type of the element
// [pv] -- Pointer to the element
//
// Notes: I8 and UI8 aren't allowed in safearrays in NT 5, but they
// will be someday.
//
// History: 9-Jun-98 dlee Created
//
//----------------------------------------------------------------------------
void SARenderElementFormatted( COutputFormat & outputFormat, CVirtualString & vString, VARTYPE vt, void * pv ) { ciGibDebugOut(( DEB_ITRACE, "vt %#x, pv %#x\n", vt, pv ));
// Recurse if we have a nested VT_ARRAY in an array element.
if ( VT_ARRAY & vt ) { SAFEARRAY *psa = *(SAFEARRAY **) pv; RenderSafeArray( vt & ~VT_ARRAY, psa, outputFormat, vString, TRUE ); return; }
WCHAR awcTmp[ maxFloatSize ]; const ULONG cwcTmp = sizeof awcTmp / sizeof awcTmp[0]; ULONG cwc = 0;
switch ( vt ) { case VT_UI1: { cwc = outputFormat.FormatNumber( (ULONG) * (BYTE *) pv, awcTmp, cwcTmp ); break; } case VT_I1: { cwc = outputFormat.FormatNumber( (LONG) * (signed char *) pv, awcTmp, cwcTmp ); break; } case VT_UI2: { USHORT us; RtlCopyMemory( &us, pv, sizeof us ); cwc = outputFormat.FormatNumber( (ULONG) us, awcTmp, cwcTmp ); break; } case VT_I2: { SHORT s; RtlCopyMemory( &s, pv, sizeof s ); cwc = outputFormat.FormatNumber( (LONG) s, awcTmp, cwcTmp ); break; } case VT_UI4: case VT_UINT: { ULONG ul; RtlCopyMemory( &ul, pv, sizeof ul ); cwc = outputFormat.FormatNumber( ul, awcTmp, cwcTmp ); break; } case VT_I4: case VT_ERROR: case VT_INT: { LONG l; RtlCopyMemory( &l, pv, sizeof l ); cwc = outputFormat.FormatNumber( l, awcTmp, cwcTmp ); break; } case VT_UI8: { unsigned __int64 ui; RtlCopyMemory( &ui, pv, sizeof ui ); cwc = outputFormat.FormatNumber( ui, awcTmp, cwcTmp ); break; } case VT_I8: { __int64 i; RtlCopyMemory( &i, pv, sizeof i ); cwc = outputFormat.FormatNumber( i, awcTmp, cwcTmp ); break; } case VT_R4: { float f; RtlCopyMemory( &f, pv, sizeof f ); cwc = outputFormat.FormatFloat( f, fltPrec, awcTmp, cwcTmp ); break; } case VT_R8: { double d; RtlCopyMemory( &d, pv, sizeof d ); cwc = outputFormat.FormatFloat( d, dblPrec, awcTmp, cwcTmp ); break; } case VT_DECIMAL: { double d; VarR8FromDec( (DECIMAL *) pv, &d ); cwc = outputFormat.FormatFloat( d, dblPrec, awcTmp, cwcTmp ); break; } case VT_CY: { double d; VarR8FromCy( * (CY *) pv, &d ); cwc = outputFormat.FormatFloat( d, dblPrec, awcTmp, cwcTmp ); break; } case VT_VARIANT: { PROPVARIANT & Var = * (PROPVARIANT *) pv; SARenderElementFormatted( outputFormat, vString, Var.vt, & Var.lVal ); break; } default : { ciGibDebugOut(( DEB_ERROR, "unexpected numeric sa element type %#x\n", vt )); Win4Assert( !"unexpected numeric safearray element type" ); break; } }
vString.StrCat( awcTmp, cwc ); } //SARenderElementFormatted
//+---------------------------------------------------------------------------
//
// Function: SARenderElementRaw
//
// Synopsis: Appends the "raw" string form a safearray element to
// a virtual string. Numbers are raw when they don't have
// formatting like commas.
//
// Arguments: [outputFormat] -- The output format to use
// [vString] -- Where the result is appended
// [vt] -- Type of the element
// [pv] -- Pointer to the element
//
// Notes: I8 and UI8 aren't allowed in safearrays in NT 5, but they
// will be someday.
//
// History: 9-Jun-98 dlee Created
//
//----------------------------------------------------------------------------
void SARenderElementRaw( COutputFormat & outputFormat, CVirtualString & vString, VARTYPE vt, void * pv ) { ciGibDebugOut(( DEB_ITRACE, "vt %#x, pv %#x\n", vt, pv ));
// Recurse if we have a nested VT_ARRAY in an array element.
if ( VT_ARRAY & vt ) { SAFEARRAY *psa = *(SAFEARRAY **) pv; RenderSafeArray( vt & ~VT_ARRAY, psa, outputFormat, vString, FALSE ); return; }
WCHAR awcTmp[ maxFloatSize ]; const ULONG cwcTmp = sizeof awcTmp / sizeof awcTmp[0]; ULONG cwc = 0;
switch ( vt ) { case VT_EMPTY: case VT_NULL: { break; } case VT_BSTR: { BSTR bstr = *(BSTR *) pv; vString.StrCat( bstr ); break; } case VT_BOOL: { VARIANT_BOOL vb; RtlCopyMemory( &vb, pv, sizeof vb ); wcscpy( awcTmp, ( VARIANT_FALSE == vb ) ? L"FALSE" : L"TRUE" ); cwc = wcslen( awcTmp); break; } case VT_DATE: { SYSTEMTIME stUTC; DATE date; RtlCopyMemory( &date, pv, sizeof date ); if ( VariantTimeToSystemTime( date, &stUTC ) ) cwc = outputFormat.FormatDateTime( stUTC, awcTmp, cwcTmp ); break; } case VT_UI1: { IDQ_ultow( (ULONG) * (BYTE *) pv, awcTmp ); cwc = wcslen( awcTmp ); break; } case VT_I1: { IDQ_ltow( (LONG) * (signed char *) pv, awcTmp ); cwc = wcslen( awcTmp ); break; } case VT_UI2: { USHORT us; RtlCopyMemory( &us, pv, sizeof us ); IDQ_ultow( (ULONG) us, awcTmp ); cwc = wcslen( awcTmp ); break; } case VT_I2: { SHORT s; RtlCopyMemory( &s, pv, sizeof s ); IDQ_ltow( (LONG) s, awcTmp ); cwc = wcslen( awcTmp ); break; } case VT_UI4: case VT_UINT: { ULONG ul; RtlCopyMemory( &ul, pv, sizeof ul ); IDQ_ultow( ul, awcTmp ); cwc = wcslen( awcTmp ); break; } case VT_I4: case VT_ERROR: case VT_INT: { LONG l; RtlCopyMemory( &l, pv, sizeof l ); IDQ_ltow( l, awcTmp ); cwc = wcslen( awcTmp ); break; } case VT_UI8: { unsigned __int64 ui; RtlCopyMemory( &ui, pv, sizeof ui ); IDQ_ulltow( ui, awcTmp ); cwc = wcslen( awcTmp ); break; } case VT_I8: { __int64 i; RtlCopyMemory( &i, pv, sizeof i ); IDQ_lltow( i, awcTmp ); cwc = wcslen( awcTmp ); break; } case VT_R4: { float f; RtlCopyMemory( &f, pv, sizeof f ); cwc = outputFormat.FormatFloatRaw( f, fltPrec, awcTmp, cwcTmp ); break; } case VT_R8: { double d; RtlCopyMemory( &d, pv, sizeof d ); cwc = outputFormat.FormatFloatRaw( d, dblPrec, awcTmp, cwcTmp ); break; } case VT_DECIMAL: { double d; VarR8FromDec( (DECIMAL *) pv, &d ); cwc = outputFormat.FormatFloatRaw( d, dblPrec, awcTmp, cwcTmp ); break; } case VT_CY: { double d; VarR8FromCy( * (CY *) pv, &d ); cwc = outputFormat.FormatFloatRaw( d, dblPrec, awcTmp, cwcTmp ); break; } case VT_VARIANT: { PROPVARIANT & Var = * (PROPVARIANT *) pv; SARenderElementRaw( outputFormat, vString, Var.vt, & Var.lVal ); break; } default : { ciGibDebugOut(( DEB_ERROR, "unexpected sa element type %#x\n", vt )); Win4Assert( !"unexpected safearray element type" ); break; } }
vString.StrCat( awcTmp, cwc ); } //SARenderElementRaw
//+---------------------------------------------------------------------------
//
// Function: GetVectorFormatting
//
// Synopsis: Retrieves the vector formatting strings for a given type.
// Only safearray element datatypes are handled here.
//
// Arguments: [pwcPre] -- Returns the vector prefix string
// [pwcSep] -- Returns the vector separator string
// [pwcSuf] -- Returns the vector suffix string
//
// History: 9-Jun-98 dlee Created
//
//----------------------------------------------------------------------------
void GetVectorFormatting( WCHAR const * & pwcPre, WCHAR const * & pwcSep, WCHAR const * & pwcSuf, VARTYPE vt, COutputFormat & outputFormat ) { Win4Assert( 0 == ( vt & VT_ARRAY ) );
switch ( vt ) { case VT_CY: pwcPre = outputFormat.GetCurrencyVectorPrefix(); pwcSep = outputFormat.GetCurrencyVectorSeparator(); pwcSuf = outputFormat.GetCurrencyVectorSuffix(); break; case VT_DATE: pwcPre = outputFormat.GetDateVectorPrefix(); pwcSep = outputFormat.GetDateVectorSeparator(); pwcSuf = outputFormat.GetDateVectorSuffix(); break; case VT_BOOL: pwcPre = outputFormat.GetBoolVectorPrefix(); pwcSep = outputFormat.GetBoolVectorSeparator(); pwcSuf = outputFormat.GetBoolVectorSuffix(); break; case VT_BSTR: pwcPre = outputFormat.GetStringVectorPrefix(); pwcSep = outputFormat.GetStringVectorSeparator(); pwcSuf = outputFormat.GetStringVectorSuffix(); break; case VT_VARIANT: case VT_EMPTY: case VT_NULL: case VT_I1: case VT_UI1: case VT_I2: case VT_UI2: case VT_I4: case VT_INT: case VT_UI4: case VT_UINT: case VT_I8: case VT_UI8: case VT_R4: case VT_R8: case VT_DECIMAL: case VT_ERROR: pwcPre = outputFormat.GetNumberVectorPrefix(); pwcSep = outputFormat.GetNumberVectorSeparator(); pwcSuf = outputFormat.GetNumberVectorSuffix(); break; default: ciGibDebugOut(( DEB_ERROR, "GetVectorFormatting unknown type %#x\n", vt )); Win4Assert( !"GetVectorFormatting doesn't support type" ); break; } } //GetVectorFormatting
//+---------------------------------------------------------------------------
//
// Function: RenderSafeArray
//
// Synopsis: Appends the string form of a safearray to a virtual string.
//
// Arguments: [vt] -- Datatype of the safearray, without VT_ARRAY
// [psa] -- The safearray to format
// [outputFormat] -- How to render the result
// [vString] -- The result is appended here
// [fFormatted] -- If TRUE, formatted, otherwise raw
//
// History: 9-Jun-98 dlee Created
//
//----------------------------------------------------------------------------
void RenderSafeArray( VARTYPE vt, SAFEARRAY * psa, COutputFormat & outputFormat, CVirtualString & vString, BOOL fFormatted ) { Win4Assert( 0 == ( vt & VT_ARRAY ) );
//
// Get the array prefix, separator, and suffix
//
WCHAR const * pwcPre; WCHAR const * pwcSep; WCHAR const * pwcSuf; GetVectorFormatting( pwcPre, pwcSep, pwcSuf, vt, outputFormat );
//
// Get the dimensions of the array
//
CDynArrayInPlace<WCHAR> xOut; UINT cDim = SafeArrayGetDim( psa ); if ( 0 == cDim ) return;
XArray<LONG> xDim( cDim ); XArray<LONG> xLo( cDim ); XArray<LONG> xUp( cDim );
for ( UINT iDim = 0; iDim < cDim; iDim++ ) { SCODE sc = SafeArrayGetLBound( psa, iDim + 1, &xLo[iDim] ); if ( FAILED( sc ) ) THROW( CException( sc ) );
xDim[ iDim ] = xLo[ iDim ];
sc = SafeArrayGetUBound( psa, iDim + 1, &xUp[iDim] ); if ( FAILED( sc ) ) THROW( CException( sc ) );
ciGibDebugOut(( DEB_ITRACE, "dim %d, lo %d, up %d\n", iDim, xLo[iDim], xUp[iDim] ));
vString.StrCat( pwcPre ); }
//
// Slog through the array
//
UINT iLastDim = cDim - 1; BOOL fDone = FALSE;
while ( !fDone ) { // Inter-element formatting if not the first element
if ( xDim[ iLastDim ] != xLo[ iLastDim ] ) vString.StrCat( pwcSep );
// Get the element and render it
void *pv; SCODE sc = SafeArrayPtrOfIndex( psa, xDim.GetPointer(), &pv ); if ( FAILED( sc ) ) THROW( CException( sc ) );
if ( fFormatted ) SARenderElementFormatted( outputFormat, vString, vt, pv ); else SARenderElementRaw( outputFormat, vString, vt, pv );
// Move to the next element and carry if necessary
ULONG cOpen = 0;
for ( LONG iDim = iLastDim; iDim >= 0; iDim-- ) { if ( xDim[ iDim ] < xUp[ iDim ] ) { xDim[ iDim ] = 1 + xDim[ iDim ]; break; }
vString.StrCat( pwcSuf );
if ( 0 == iDim ) fDone = TRUE; else { cOpen++; xDim[ iDim ] = xLo[ iDim ]; } }
for ( ULONG i = 0; !fDone && i < cOpen; i++ ) vString.StrCat( pwcPre ); } } //RenderSafeArray
//+---------------------------------------------------------------------------
//
// Member: CVariable::GetStringValueFormattedRAW - public
//
// Synopsis: Not all VT types are strings. Those which are not strings
// have a string equivalent generated and stored for reuse.
//
// Arguments: [outputFormat] - contains formatting information for numbers
//
// Returns: A pointer to a string representation of the variable's value.
// Numbers are formatted.
//
// History: 26-Aug-96 KyleP Created (from GetStringValueRAW)
//
//----------------------------------------------------------------------------
WCHAR * CVariable::GetStringValueFormattedRAW( COutputFormat & outputFormat, ULONG & cwcValue ) { Win4Assert( !(_wcsRAWValue == 0 && _cwcRAWValue != 0) );
//
// Did we have a real raw value last time?
//
if ( _wcsRAWValue && _eNumType == eRawNumber ) { if ( _wcsRAWValue != _wcsNumberValue && _wcsRAWValue != _variant.pwszVal ) delete _wcsRAWValue;
_wcsRAWValue = 0; _cwcRAWValue = 0; }
if ( 0 == _wcsRAWValue ) { switch ( _variant.vt ) { case VT_UI1: _cwcRAWValue = outputFormat.FormatNumber( (ULONG) _variant.bVal, _wcsNumberValue, sizeof(_wcsNumberValue) / sizeof(WCHAR) ); _wcsRAWValue = _wcsNumberValue; _eNumType = eFormattedNumber; break;
case VT_I1: _cwcRAWValue = outputFormat.FormatNumber( (LONG) _variant.cVal, _wcsNumberValue, sizeof(_wcsNumberValue) / sizeof(WCHAR) ); _wcsRAWValue = _wcsNumberValue; _eNumType = eFormattedNumber; break;
case VT_UI2: _cwcRAWValue = outputFormat.FormatNumber( (ULONG) _variant.uiVal, _wcsNumberValue, sizeof(_wcsNumberValue) / sizeof(WCHAR) ); _wcsRAWValue = _wcsNumberValue; _eNumType = eFormattedNumber; break;
case VT_I2: _cwcRAWValue = outputFormat.FormatNumber( (LONG) _variant.iVal, _wcsNumberValue, sizeof(_wcsNumberValue) / sizeof(WCHAR) ); _wcsRAWValue = _wcsNumberValue; _eNumType = eFormattedNumber; break;
case VT_UI4: case VT_UINT: _cwcRAWValue = outputFormat.FormatNumber( (ULONG) _variant.ulVal, _wcsNumberValue, sizeof(_wcsNumberValue) / sizeof(WCHAR) ); _wcsRAWValue = _wcsNumberValue; _eNumType = eFormattedNumber; break;
case VT_I4: case VT_INT: case VT_ERROR: _cwcRAWValue = outputFormat.FormatNumber( (LONG) _variant.lVal, _wcsNumberValue, sizeof(_wcsNumberValue) / sizeof(WCHAR) ); _wcsRAWValue = _wcsNumberValue; _eNumType = eFormattedNumber; break;
case VT_UI8: _cwcRAWValue = outputFormat.FormatNumber( _variant.uhVal.QuadPart, _wcsNumberValue, sizeof(_wcsNumberValue) / sizeof(WCHAR) ); _wcsRAWValue = _wcsNumberValue; _eNumType = eFormattedNumber; break;
case VT_I8: _cwcRAWValue = outputFormat.FormatNumber( _variant.hVal.QuadPart, _wcsNumberValue, sizeof(_wcsNumberValue) / sizeof(WCHAR) ); _wcsRAWValue = _wcsNumberValue; _eNumType = eFormattedNumber; break;
case VT_R4: { WCHAR awchOutput[maxFloatSize];
_cwcRAWValue = outputFormat.FormatFloat( _variant.fltVal, fltPrec, awchOutput, maxFloatSize );
if ( _cwcRAWValue < cwcNumberValue ) _wcsRAWValue = _wcsNumberValue; else _wcsRAWValue = new WCHAR[ 1 + _cwcRAWValue ];
RtlCopyMemory( _wcsRAWValue, awchOutput, (1 + _cwcRAWValue) * sizeof WCHAR ); _eNumType = eFormattedNumber; break; }
case VT_R8: case VT_DECIMAL: { double dblValue = _variant.dblVal; if ( VT_DECIMAL == _variant.vt ) VarR8FromDec( &_variant.decVal, &dblValue );
// Big enough for a 1e308 + 9 decimal places + sign
WCHAR awchOutput[maxFloatSize];
_cwcRAWValue = outputFormat.FormatFloat( dblValue, dblPrec, awchOutput, maxFloatSize );
if ( _cwcRAWValue < cwcNumberValue ) _wcsRAWValue = _wcsNumberValue; else _wcsRAWValue = new WCHAR[ 1 + _cwcRAWValue ];
RtlCopyMemory( _wcsRAWValue, awchOutput, (1 + _cwcRAWValue) * sizeof WCHAR ); _eNumType = eFormattedNumber; break; }
case VT_CY: _cwcRAWValue = outputFormat.FormatCurrency( _variant.cyVal, _wcsNumberValue, sizeof(_wcsNumberValue) / sizeof(WCHAR) ); _wcsRAWValue = _wcsNumberValue; _eNumType = eFormattedNumber; break;
case VT_UI1 | VT_VECTOR: case VT_I1 | VT_VECTOR: { _eNumType = eFormattedNumber; CVirtualString vString( 0x200 ); vString.StrCat( outputFormat.GetNumberVectorPrefix() );
for ( unsigned iValue=0; iValue<_variant.caub.cElems; iValue++ ) { if ( 0 != iValue ) vString.StrCat( outputFormat.GetNumberVectorSeparator() );
if ( (VT_UI1 | VT_VECTOR) == _variant.vt ) _cwcRAWValue = outputFormat.FormatNumber( (ULONG) _variant.caub.pElems[iValue], _wcsNumberValue, sizeof(_wcsNumberValue) / sizeof(WCHAR) ); else _cwcRAWValue = outputFormat.FormatNumber( (LONG) _variant.cac.pElems[iValue], _wcsNumberValue, sizeof(_wcsNumberValue) / sizeof(WCHAR) );
vString.StrCat( _wcsNumberValue, _cwcRAWValue ); }
vString.StrCat( outputFormat.GetNumberVectorSuffix() );
_wcsRAWValue = vString.StrDup(); _cwcRAWValue = vString.StrLen(); break; }
case VT_I2 | VT_VECTOR: case VT_UI2 | VT_VECTOR: { _eNumType = eFormattedNumber; CVirtualString vString( 0x200 ); vString.StrCat( outputFormat.GetNumberVectorPrefix() );
for ( unsigned iValue=0; iValue<_variant.caui.cElems; iValue++ ) { if ( 0 != iValue ) vString.StrCat( outputFormat.GetNumberVectorSeparator() );
if ( (VT_UI2 | VT_VECTOR) == _variant.vt ) _cwcRAWValue = outputFormat.FormatNumber( (ULONG) _variant.caui.pElems[iValue], _wcsNumberValue, sizeof(_wcsNumberValue) / sizeof(WCHAR) ); else _cwcRAWValue = outputFormat.FormatNumber( (LONG) _variant.cai.pElems[iValue], _wcsNumberValue, sizeof(_wcsNumberValue) / sizeof(WCHAR) );
vString.StrCat( _wcsNumberValue, _cwcRAWValue ); }
vString.StrCat( outputFormat.GetNumberVectorSuffix() );
_wcsRAWValue = vString.StrDup(); _cwcRAWValue = vString.StrLen(); break; }
case VT_R4 | VT_VECTOR: case VT_I4 | VT_VECTOR: case VT_UI4 | VT_VECTOR: case VT_ERROR | VT_VECTOR: { _eNumType = eFormattedNumber; CVirtualString vString( 0x200 ); vString.StrCat( outputFormat.GetNumberVectorPrefix() );
for ( unsigned iValue=0; iValue<_variant.caul.cElems; iValue++ ) { if ( 0 != iValue ) vString.StrCat( outputFormat.GetNumberVectorSeparator() );
if ( (VT_R4 | VT_VECTOR) == _variant.vt ) _cwcRAWValue = outputFormat.FormatFloat( _variant.caflt.pElems[iValue], fltPrec, _wcsNumberValue, sizeof(_wcsNumberValue) / sizeof(WCHAR) ); else if ( (VT_UI4 | VT_VECTOR) == _variant.vt ) _cwcRAWValue = outputFormat.FormatNumber( _variant.caul.pElems[iValue], _wcsNumberValue, sizeof(_wcsNumberValue) / sizeof(WCHAR) ); else _cwcRAWValue = outputFormat.FormatNumber( _variant.cal.pElems[iValue], _wcsNumberValue, sizeof(_wcsNumberValue) / sizeof(WCHAR) );
vString.StrCat( _wcsNumberValue, _cwcRAWValue ); }
vString.StrCat( outputFormat.GetNumberVectorSuffix() );
_wcsRAWValue = vString.StrDup(); _cwcRAWValue = vString.StrLen(); break; }
case VT_I8 | VT_VECTOR: case VT_UI8 | VT_VECTOR: case VT_R8 | VT_VECTOR: { _eNumType = eFormattedNumber; CVirtualString vString( 0x200 ); vString.StrCat( outputFormat.GetNumberVectorPrefix() );
for ( unsigned iValue=0; iValue<_variant.cadbl.cElems; iValue++ ) { if ( 0 != iValue ) vString.StrCat( outputFormat.GetNumberVectorSeparator() );
if ( (VT_I8 | VT_VECTOR) == _variant.vt ) _cwcRAWValue = outputFormat.FormatNumber( (_int64) _variant.cah.pElems[iValue].QuadPart, _wcsNumberValue, sizeof(_wcsNumberValue) / sizeof(WCHAR) ); else if ( (VT_UI8 | VT_VECTOR) == _variant.vt ) _cwcRAWValue = outputFormat.FormatNumber( (unsigned _int64) _variant.cauh.pElems[iValue].QuadPart, _wcsNumberValue, sizeof(_wcsNumberValue) / sizeof(WCHAR) ); else _cwcRAWValue = outputFormat.FormatFloat( _variant.cadbl.pElems[iValue], dblPrec, _wcsNumberValue, sizeof(_wcsNumberValue) / sizeof(WCHAR) );
vString.StrCat( _wcsNumberValue, _cwcRAWValue ); }
vString.StrCat( outputFormat.GetNumberVectorSuffix() );
_wcsRAWValue = vString.StrDup(); _cwcRAWValue = vString.StrLen(); break; }
case VT_CY | VT_VECTOR: { _eNumType = eFormattedNumber; CVirtualString vString( 0x200 ); vString.StrCat( outputFormat.GetCurrencyVectorPrefix() );
for ( unsigned iValue=0; iValue<_variant.cacy.cElems; iValue++ ) { if ( 0 != iValue ) vString.StrCat( outputFormat.GetCurrencyVectorSeparator() );
_cwcRAWValue = outputFormat.FormatCurrency( _variant.cacy.pElems[iValue], _wcsNumberValue, sizeof(_wcsNumberValue) / sizeof(WCHAR) ); vString.StrCat( _wcsNumberValue, _cwcRAWValue ); }
vString.StrCat( outputFormat.GetCurrencyVectorSuffix() );
_wcsRAWValue = vString.StrDup(); _cwcRAWValue = vString.StrLen(); break; }
case VT_ARRAY | VT_I1 : case VT_ARRAY | VT_UI1: case VT_ARRAY | VT_I2 : case VT_ARRAY | VT_UI2 : case VT_ARRAY | VT_I4 : case VT_ARRAY | VT_INT : case VT_ARRAY | VT_UI4 : case VT_ARRAY | VT_UINT : case VT_ARRAY | VT_CY : case VT_ARRAY | VT_DECIMAL : case VT_ARRAY | VT_ERROR: { _eNumType = eFormattedNumber; CVirtualString vString( 0x200 );
RenderSafeArray( _variant.vt & ~VT_ARRAY, _variant.parray, outputFormat, vString, TRUE ); _wcsRAWValue = vString.StrDup(); _cwcRAWValue = vString.StrLen(); break; }
default: { Win4Assert( _eNumType == eNotANumber ); GetStringValueRAW( outputFormat, cwcValue ); break; } } }
#if (DBG == 1)
if ( _wcsRAWValue != 0 ) { Win4Assert( wcslen(_wcsRAWValue) == _cwcRAWValue ); } #endif // DBG == 1
Win4Assert( !(_wcsRAWValue == 0 && _cwcRAWValue != 0) );
cwcValue = _cwcRAWValue; return _wcsRAWValue; }
//+---------------------------------------------------------------------------
//
// Member: CVariable::GetStringValueRAW - public
//
// Synopsis: Not all VT types are strings. Those which are not strings
// have a string equivalent generated and stored for reuse.
//
// Arguments: [outputFormat] - contains formatting information for numbers
//
// Returns: A pointer to a string representation of the variable's value.
//
// History: 96/Jan/03 DwightKr Created.
// 96/Mar/29 DwightKr Add support for deferred VT_LPWSTR
// values
//
//----------------------------------------------------------------------------
WCHAR * CVariable::GetStringValueRAW( COutputFormat & outputFormat, ULONG & cwcValue) { Win4Assert( !(_wcsRAWValue == 0 && _cwcRAWValue != 0) );
//
// Did we have a formatted raw value last time?
//
if ( _wcsRAWValue && _eNumType == eFormattedNumber ) { if ( _wcsRAWValue != _wcsNumberValue && _wcsRAWValue != _variant.pwszVal ) delete _wcsRAWValue;
_wcsRAWValue = 0; _cwcRAWValue = 0; }
if ( 0 == _wcsRAWValue ) { switch ( _variant.vt ) { case VT_LPWSTR: //
// if it's a deferred value, load it now
//
if ( (_ulFlags & eParamDeferredValue) != 0 ) { XArray<WCHAR> wcsValue; ULONG cwcValue;
if ( outputFormat.GetCGIVariableW(_wcsName, wcsValue, cwcValue) ) { _wcsRAWValue = wcsValue.Acquire(); _cwcRAWValue = cwcValue;
ciGibDebugOut(( DEB_ITRACE, "Loading deferred value for %ws=%ws\n", _wcsName, _wcsRAWValue )); } else { ciGibDebugOut(( DEB_ITRACE, "Unable to load deferred value for %ws\n", _wcsName ));
_variant.vt = VT_EMPTY; _wcsRAWValue = _wcsNumberValue; *_wcsRAWValue = 0; _cwcRAWValue = 0; }
break; }
// fall through if not a deferred value
case VT_EMPTY: _wcsRAWValue = _wcsNumberValue; *_wcsRAWValue = 0; _cwcRAWValue = 0; break;
case VT_BSTR: _wcsRAWValue = _variant.bstrVal; _cwcRAWValue = wcslen( _wcsRAWValue ); break;
case VT_LPSTR: { ULONG cbBuffer = strlen( _variant.pszVal ) + 1; XArray<WCHAR> pwBuffer;
_cwcRAWValue = MultiByteToXArrayWideChar( (BYTE * const) _variant.pszVal, cbBuffer, outputFormat.CodePage(), pwBuffer );
_wcsRAWValue = pwBuffer.Acquire(); } break;
case VT_UI1: IDQ_ultow( (ULONG) _variant.bVal, _wcsNumberValue ); _wcsRAWValue = _wcsNumberValue; _cwcRAWValue = wcslen( _wcsRAWValue ); _eNumType = eRawNumber; break;
case VT_I1: IDQ_ltow( (LONG) _variant.cVal, _wcsNumberValue ); _wcsRAWValue = _wcsNumberValue; _cwcRAWValue = wcslen( _wcsRAWValue ); _eNumType = eRawNumber; break;
case VT_UI2: IDQ_ultow( (ULONG) _variant.uiVal, _wcsNumberValue ); _wcsRAWValue = _wcsNumberValue; _cwcRAWValue = wcslen( _wcsRAWValue ); _eNumType = eRawNumber; break;
case VT_I2: IDQ_ltow( (LONG) _variant.iVal, _wcsNumberValue ); _wcsRAWValue = _wcsNumberValue; _cwcRAWValue = wcslen( _wcsRAWValue ); _eNumType = eRawNumber; break;
case VT_UI4: case VT_UINT: IDQ_ultow( _variant.ulVal, _wcsNumberValue ); _wcsRAWValue = _wcsNumberValue; _cwcRAWValue = wcslen( _wcsRAWValue ); _eNumType = eRawNumber; break;
case VT_I4: case VT_INT: case VT_ERROR: IDQ_ltow( _variant.lVal, _wcsNumberValue ); _wcsRAWValue = _wcsNumberValue; _cwcRAWValue = wcslen( _wcsRAWValue ); _eNumType = eRawNumber; break;
case VT_UI8: IDQ_ulltow( _variant.uhVal.QuadPart, _wcsNumberValue ); _wcsRAWValue = _wcsNumberValue; _cwcRAWValue = wcslen( _wcsRAWValue ); _eNumType = eRawNumber; break;
case VT_I8: IDQ_lltow( _variant.hVal.QuadPart, _wcsNumberValue ); _wcsRAWValue = _wcsNumberValue; _cwcRAWValue = wcslen( _wcsRAWValue ); _eNumType = eRawNumber; break;
case VT_R4: { // Big enough for a 1e308 + 9 decimal places + sign
WCHAR awc[maxFloatSize];
outputFormat.FormatFloatRaw( _variant.fltVal, fltPrec, awc, maxFloatSize ); _cwcRAWValue = wcslen( awc );
if ( _cwcRAWValue < cwcNumberValue ) _wcsRAWValue = _wcsNumberValue; else _wcsRAWValue = new WCHAR[ 1 + _cwcRAWValue ];
RtlCopyMemory( _wcsRAWValue, awc, (1 + _cwcRAWValue) * sizeof WCHAR ); _eNumType = eRawNumber; } break;
case VT_R8: case VT_DECIMAL: { double dblValue = _variant.dblVal; if ( VT_DECIMAL == _variant.vt ) VarR8FromDec( &_variant.decVal, &dblValue );
// Big enough for a 1e308 + 9 decimal places + sign
WCHAR awc[maxFloatSize];
outputFormat.FormatFloatRaw( dblValue, dblPrec, awc, maxFloatSize ); _cwcRAWValue = wcslen( awc );
if ( _cwcRAWValue < cwcNumberValue ) _wcsRAWValue = _wcsNumberValue; else _wcsRAWValue = new WCHAR[ 1 + _cwcRAWValue ];
RtlCopyMemory( _wcsRAWValue, awc, (1 + _cwcRAWValue) * sizeof WCHAR ); _eNumType = eRawNumber; } break;
case VT_DATE: { //
// variantdate => dosdate => utcfiletime
//
SYSTEMTIME stUTC; if ( VariantTimeToSystemTime(_variant.date, &stUTC ) ) { _cwcRAWValue = outputFormat.FormatDateTime( stUTC, _wcsNumberValue, sizeof(_wcsNumberValue) / sizeof(WCHAR) ); _wcsRAWValue = _wcsNumberValue; } else { _wcsRAWValue = _wcsNumberValue; *_wcsRAWValue = 0; _cwcRAWValue = 0; } } break;
case VT_FILETIME: _cwcRAWValue = outputFormat.FormatDateTime( _variant.filetime, _wcsNumberValue, sizeof(_wcsNumberValue) / sizeof(WCHAR) ); _wcsRAWValue = _wcsNumberValue; break;
case VT_BOOL: _wcsRAWValue = _wcsNumberValue; wcscpy( _wcsRAWValue, _variant.boolVal == VARIANT_FALSE ? L"FALSE" : L"TRUE" ); _cwcRAWValue = wcslen( _wcsRAWValue ); break;
case VT_CLSID: _wcsRAWValue = _wcsNumberValue; _cwcRAWValue = swprintf( _wcsRAWValue, L"%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", _variant.puuid->Data1, _variant.puuid->Data2, _variant.puuid->Data3, _variant.puuid->Data4[0], _variant.puuid->Data4[1], _variant.puuid->Data4[2], _variant.puuid->Data4[3], _variant.puuid->Data4[4], _variant.puuid->Data4[5], _variant.puuid->Data4[6], _variant.puuid->Data4[7] ); break;
case VT_CY: { double dblValue; VarR8FromCy( _variant.cyVal, &dblValue );
// Big enough for a 1e308 + 9 decimal places + sign
WCHAR awc[maxFloatSize];
_cwcRAWValue = swprintf( awc, L"%lf", dblValue );
if ( _cwcRAWValue < cwcNumberValue ) _wcsRAWValue = _wcsNumberValue; else _wcsRAWValue = new WCHAR[ 1 + _cwcRAWValue ];
RtlCopyMemory( _wcsRAWValue, awc, (1 + _cwcRAWValue) * sizeof WCHAR ); _eNumType = eRawNumber; } break;
//
// Vectors only below this point
//
case VT_LPWSTR | VT_VECTOR: { CVirtualString vString( 0x200 ); vString.StrCat( outputFormat.GetStringVectorPrefix() );
for ( unsigned iValue=0; iValue<_variant.calpwstr.cElems; iValue++ ) { if ( 0 != iValue ) vString.StrCat( outputFormat.GetStringVectorSeparator() );
vString.StrCat( _variant.calpwstr.pElems[iValue] ); }
vString.StrCat( outputFormat.GetStringVectorSuffix() ); _wcsRAWValue = vString.StrDup(); _cwcRAWValue = vString.StrLen(); } break;
case VT_BSTR | VT_VECTOR: { CVirtualString vString( 0x200 ); vString.StrCat( outputFormat.GetStringVectorPrefix() );
for ( unsigned iValue=0; iValue<_variant.cabstr.cElems; iValue++ ) { if ( 0 != iValue ) vString.StrCat( outputFormat.GetStringVectorSeparator() );
vString.StrCat( _variant.cabstr.pElems[iValue] ); }
vString.StrCat( outputFormat.GetStringVectorSuffix() ); _wcsRAWValue = vString.StrDup(); _cwcRAWValue = vString.StrLen(); } break;
case VT_LPSTR | VT_VECTOR: { CVirtualString vString( 0x200 ); vString.StrCat( outputFormat.GetStringVectorPrefix() );
for ( unsigned iValue=0; iValue<_variant.calpstr.cElems; iValue++ ) { if ( 0 != iValue ) vString.StrCat( outputFormat.GetStringVectorSeparator() );
ULONG cbBuffer = strlen( _variant.calpstr.pElems[iValue] ) + 1; XArray<WCHAR> pwBuffer;
_cwcRAWValue = MultiByteToXArrayWideChar( (BYTE * const) _variant.calpstr.pElems[iValue], cbBuffer, outputFormat.CodePage(), pwBuffer );
vString.StrCat( pwBuffer.Get(), _cwcRAWValue ); }
vString.StrCat( outputFormat.GetStringVectorSuffix() ); _wcsRAWValue = vString.StrDup(); _cwcRAWValue = vString.StrLen(); } break;
case VT_UI1 | VT_VECTOR: case VT_I1 | VT_VECTOR: { _eNumType = eRawNumber; CVirtualString vString( 0x200 ); vString.StrCat( outputFormat.GetNumberVectorPrefix() );
for ( unsigned iValue=0; iValue<_variant.caub.cElems; iValue++ ) { if ( 0 != iValue ) vString.StrCat( outputFormat.GetNumberVectorSeparator() );
if ( (VT_UI1 | VT_VECTOR) == _variant.vt ) { IDQ_ultow( (ULONG) _variant.caub.pElems[iValue], _wcsNumberValue ); _wcsRAWValue = _wcsNumberValue; _cwcRAWValue = wcslen( _wcsRAWValue ); } else { IDQ_ltow( (LONG) _variant.cac.pElems[iValue], _wcsNumberValue ); _wcsRAWValue = _wcsNumberValue; _cwcRAWValue = wcslen( _wcsRAWValue ); }
vString.StrCat( _wcsNumberValue, _cwcRAWValue ); }
vString.StrCat( outputFormat.GetNumberVectorSuffix() );
_wcsRAWValue = vString.StrDup(); _cwcRAWValue = vString.StrLen(); } break;
case VT_I2 | VT_VECTOR: case VT_UI2 | VT_VECTOR: { _eNumType = eRawNumber; CVirtualString vString( 0x200 ); vString.StrCat( outputFormat.GetNumberVectorPrefix() );
for ( unsigned iValue=0; iValue<_variant.caui.cElems; iValue++ ) { if ( 0 != iValue ) vString.StrCat( outputFormat.GetNumberVectorSeparator() );
if ( (VT_UI2 | VT_VECTOR) == _variant.vt ) { IDQ_ultow( (ULONG) _variant.caui.pElems[iValue], _wcsNumberValue ); _wcsRAWValue = _wcsNumberValue; _cwcRAWValue = wcslen( _wcsRAWValue ); } else { IDQ_ltow( (LONG) _variant.cai.pElems[iValue], _wcsNumberValue ); _wcsRAWValue = _wcsNumberValue; _cwcRAWValue = wcslen( _wcsRAWValue ); }
vString.StrCat( _wcsNumberValue, _cwcRAWValue ); }
vString.StrCat( outputFormat.GetNumberVectorSuffix() );
_wcsRAWValue = vString.StrDup(); _cwcRAWValue = vString.StrLen(); } break;
case VT_I4 | VT_VECTOR: case VT_UI4 | VT_VECTOR: case VT_I8 | VT_VECTOR: case VT_UI8 | VT_VECTOR: { _eNumType = eRawNumber; CVirtualString vString( 0x200 ); vString.StrCat( outputFormat.GetNumberVectorPrefix() );
for ( unsigned iValue=0; iValue<_variant.caul.cElems; iValue++ ) { if ( 0 != iValue ) vString.StrCat( outputFormat.GetNumberVectorSeparator() );
if ( (VT_I4 | VT_VECTOR) == _variant.vt ) { IDQ_ltow( _variant.cal.pElems[iValue], _wcsNumberValue ); _wcsRAWValue = _wcsNumberValue; _cwcRAWValue = wcslen( _wcsRAWValue ); } else if ( (VT_UI4 | VT_VECTOR) == _variant.vt ) { IDQ_ultow( _variant.caul.pElems[iValue], _wcsNumberValue ); _wcsRAWValue = _wcsNumberValue; _cwcRAWValue = wcslen( _wcsRAWValue ); } else if ( (VT_I8 | VT_VECTOR) == _variant.vt ) { IDQ_lltow( _variant.cah.pElems[iValue].QuadPart, _wcsNumberValue ); _wcsRAWValue = _wcsNumberValue; _cwcRAWValue = wcslen( _wcsRAWValue ); } else { IDQ_ulltow( _variant.cauh.pElems[iValue].QuadPart, _wcsNumberValue ); _wcsRAWValue = _wcsNumberValue; _cwcRAWValue = wcslen( _wcsRAWValue ); }
vString.StrCat( _wcsNumberValue, _cwcRAWValue ); }
vString.StrCat( outputFormat.GetNumberVectorSuffix() );
_wcsRAWValue = vString.StrDup(); _cwcRAWValue = vString.StrLen(); } break;
case VT_R4 | VT_VECTOR: case VT_R8 | VT_VECTOR: { _eNumType = eRawNumber; CVirtualString vString( 0x200 ); vString.StrCat( outputFormat.GetNumberVectorPrefix() );
// Big enough for a 1e308 + 9 decimal places + sign
WCHAR awc[maxFloatSize];
for ( unsigned iValue=0; iValue<_variant.cadbl.cElems; iValue++ ) { if ( 0 != iValue ) vString.StrCat( outputFormat.GetNumberVectorSeparator() );
if ( (VT_R4 | VT_VECTOR) == _variant.vt ) { outputFormat.FormatFloatRaw( _variant.caflt.pElems[iValue], fltPrec, awc, maxFloatSize ); _cwcRAWValue = wcslen( awc ); } else { outputFormat.FormatFloatRaw( _variant.cadbl.pElems[iValue], dblPrec, awc, maxFloatSize ); _cwcRAWValue = wcslen( awc ); }
vString.StrCat( awc, _cwcRAWValue ); }
vString.StrCat( outputFormat.GetNumberVectorSuffix() );
_wcsRAWValue = vString.StrDup(); _cwcRAWValue = vString.StrLen(); } break;
case VT_DATE | VT_VECTOR: { CVirtualString vString( 0x200 ); vString.StrCat( outputFormat.GetDateVectorPrefix() );
for ( unsigned iValue=0; iValue<_variant.cadate.cElems; iValue++ ) { if ( 0 != iValue ) vString.StrCat( outputFormat.GetDateVectorSeparator() );
//
// variantdate => dosdate => localfiletime => utcfiletime
//
SYSTEMTIME stUTC; if ( VariantTimeToSystemTime(_variant.cadate.pElems[iValue], &stUTC ) ) { _cwcRAWValue = outputFormat.FormatDateTime( stUTC, _wcsNumberValue, sizeof(_wcsNumberValue) / sizeof(WCHAR) ); } else { *_wcsNumberValue = 0; _cwcRAWValue = 0; }
vString.StrCat( _wcsNumberValue, _cwcRAWValue ); }
vString.StrCat( outputFormat.GetDateVectorSuffix() );
_wcsRAWValue = vString.StrDup(); _cwcRAWValue = vString.StrLen(); } break;
case VT_FILETIME | VT_VECTOR: { CVirtualString vString( 0x200 ); vString.StrCat( outputFormat.GetDateVectorPrefix() );
for ( unsigned iValue=0; iValue<_variant.cafiletime.cElems; iValue++ ) { if ( 0 != iValue ) vString.StrCat( outputFormat.GetDateVectorSeparator() );
_cwcRAWValue = outputFormat.FormatDateTime( _variant.cafiletime.pElems[iValue], _wcsNumberValue, sizeof(_wcsNumberValue) / sizeof(WCHAR) ); vString.StrCat( _wcsNumberValue, _cwcRAWValue ); }
vString.StrCat( outputFormat.GetDateVectorSuffix() );
_wcsRAWValue = vString.StrDup(); _cwcRAWValue = vString.StrLen(); } break;
case VT_BOOL | VT_VECTOR: { CVirtualString vString( 0x200 ); vString.StrCat( outputFormat.GetBoolVectorPrefix() );
for ( unsigned iValue=0; iValue<_variant.cabool.cElems; iValue++ ) { if ( 0 != iValue ) vString.StrCat( outputFormat.GetBoolVectorSeparator() );
vString.StrCat( _variant.cabool.pElems[iValue] == VARIANT_FALSE ? L"FALSE" : L"TRUE" ); }
vString.StrCat( outputFormat.GetBoolVectorSuffix() );
_wcsRAWValue = vString.StrDup(); _cwcRAWValue = vString.StrLen(); } break;
case VT_CLSID | VT_VECTOR: { CVirtualString vString( 0x200 ); vString.StrCat( outputFormat.GetStringVectorPrefix() );
for ( unsigned iValue=0; iValue<_variant.cauuid.cElems; iValue++ ) { if ( 0 != iValue ) vString.StrCat( outputFormat.GetStringVectorSeparator() );
_cwcRAWValue = swprintf( _wcsNumberValue, L"%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", _variant.cauuid.pElems[iValue].Data1, _variant.cauuid.pElems[iValue].Data2, _variant.cauuid.pElems[iValue].Data3, _variant.cauuid.pElems[iValue].Data4[0], _variant.cauuid.pElems[iValue].Data4[1], _variant.cauuid.pElems[iValue].Data4[2], _variant.cauuid.pElems[iValue].Data4[3], _variant.cauuid.pElems[iValue].Data4[4], _variant.cauuid.pElems[iValue].Data4[5], _variant.cauuid.pElems[iValue].Data4[6], _variant.cauuid.pElems[iValue].Data4[7] ); vString.StrCat( _wcsNumberValue, _cwcRAWValue ); }
vString.StrCat( outputFormat.GetStringVectorSuffix() );
_wcsRAWValue = vString.StrDup(); _cwcRAWValue = vString.StrLen(); } break;
case VT_CY | VT_VECTOR: { _eNumType = eRawNumber; CVirtualString vString( 0x200 ); vString.StrCat( outputFormat.GetCurrencyVectorPrefix() );
for ( unsigned iValue=0; iValue<_variant.cacy.cElems; iValue++ ) { if ( 0 != iValue ) vString.StrCat( outputFormat.GetCurrencyVectorSeparator() );
// Big enough for a 1e308 + 9 decimal places + sign
WCHAR awc[maxFloatSize];
double dblValue; VarR8FromCy( _variant.cacy.pElems[iValue], &dblValue );
_cwcRAWValue = swprintf( awc, L"%lf", dblValue );
vString.StrCat( awc, _cwcRAWValue ); }
vString.StrCat( outputFormat.GetCurrencyVectorSuffix() );
_wcsRAWValue = vString.StrDup(); _cwcRAWValue = vString.StrLen(); } break;
default: { if ( VT_ARRAY & _variant.vt ) { VARTYPE vt = _variant.vt & ~VT_ARRAY;
if ( VT_I1 == vt || VT_UI1 == vt || VT_I2 == vt || VT_UI2 == vt || VT_I4 == vt || VT_UI4 == vt || VT_INT == vt || VT_UINT == vt || VT_I8 == vt || VT_UI8 == vt || VT_R4 == vt || VT_R8 == vt || VT_CY == vt || VT_DECIMAL == vt || VT_ERROR == vt ) _eNumType = eRawNumber;
CVirtualString vString( 0x200 );
RenderSafeArray( vt, _variant.parray, outputFormat, vString, FALSE ); _wcsRAWValue = vString.StrDup(); _cwcRAWValue = vString.StrLen(); } else { _wcsRAWValue = _wcsNumberValue; *_wcsRAWValue = 0; _cwcRAWValue = 0;
ciGibDebugOut(( DEB_WARN, "Type %u not supported in out column", _variant.vt )); } } break; } }
#if (DBG == 1)
if ( _wcsRAWValue != 0 ) { Win4Assert( wcslen(_wcsRAWValue) == _cwcRAWValue ); } #endif // DBG == 1
Win4Assert( !(_wcsRAWValue == 0 && _cwcRAWValue != 0) );
cwcValue = _cwcRAWValue; return _wcsRAWValue; }
//+---------------------------------------------------------------------------
//
// Member: CVariable::DupStringValue - public
//
// Synopsis: Makes a copy of the string value of this variable
//
// Returns: A pointer to a string representation of the variable's value.
//
// History: 96/Mar/07 DwightKr Created.
//
//----------------------------------------------------------------------------
WCHAR * CVariable::DupStringValue( COutputFormat & outputFormat ) { ULONG cwcValue; WCHAR * wcsValue = GetStringValueRAW( outputFormat, cwcValue );
WCHAR * wcsCopyOfValue = new WCHAR[ cwcValue + 1 ]; RtlCopyMemory( wcsCopyOfValue, wcsValue, (cwcValue+1) * sizeof(WCHAR) );
return wcsCopyOfValue; }
//+---------------------------------------------------------------------------
//
// Member: CVariable::IsDirectlyComparable - public
//
// Synopsis: Not all VT types are are numbers. This is useful when
// attempting to compare different VT_TYPES.
//
// Returns: TRUE if the variable can be represented as a number, FALSE
// for strings, blobs, etc.
//
// History: 96/Jan/03 DwightKr Created.
//
//----------------------------------------------------------------------------
BOOL CVariable::IsDirectlyComparable() const { switch ( _variant.vt & ( ~VT_VECTOR ) ) { case VT_UI1: case VT_I1: case VT_UI2: case VT_I2: case VT_UI4: case VT_I4: case VT_UINT: case VT_INT: case VT_R4: case VT_R8: case VT_I8: case VT_UI8: case VT_BOOL: case VT_CY: case VT_DATE: case VT_FILETIME: case VT_DECIMAL: return TRUE; }
return FALSE; }
//+---------------------------------------------------------------------------
//
// Member: CVariableSet::SetVariable - public
//
// Synopsis: A assignment operator; allows the value of a variable to
// be changed.
//
// Arguments: [wcsName] - the variable name
// [pVariant] - new value for this variable
// [ulCreateFlags] - and flags associated with this variable;
// such as requiring an IRowsetScroll
//
// History: 96/Jan/03 DwightKr Created.
// 96/Apr/11 DwightKr Set back link
//
//----------------------------------------------------------------------------
CVariable * CVariableSet::SetVariable( WCHAR const * wcsName, PROPVARIANT const * pVariant, ULONG ulCreateFlags ) { Win4Assert( 0 != wcsName );
ULONG ulHash = ISAPIVariableNameHash( wcsName ); CVariable *pVariable = Find(wcsName, ulHash);
if ( 0 != pVariable ) { pVariable->SetValue( pVariant, ulCreateFlags ); } else { pVariable = new CVariable( wcsName, pVariant, ulCreateFlags );
pVariable->SetNext( _variableSet[ ulHash ] ); if ( 0 != pVariable->GetNext() ) { pVariable->GetNext()->SetBack( pVariable ); }
_variableSet[ ulHash ] = pVariable; }
return pVariable; }
//+---------------------------------------------------------------------------
//
// Member: CVariableSet::CopyStringValue - public
//
// Synopsis: A assignment operator; allows the value of a variable to
// be changed.
//
// Arguments: [wcsName] - the variable name
// [wcsValue] - value of the variable
// [ulCreateFlags] - and flags associated with this variable;
// such as requiring an IRowsetScroll
// [cwcValue] - # of chars in wcsValue or 0 if unknown
//
// History: 96/Jan/03 DwightKr Created.
//
//----------------------------------------------------------------------------
void CVariableSet::CopyStringValue( WCHAR const * wcsName, WCHAR const * wcsValue, ULONG ulCreateFlags, ULONG cwcValue ) { Win4Assert( 0 != wcsName ); Win4Assert( 0 != wcsValue );
if ( 0 == cwcValue ) cwcValue = wcslen( wcsValue );
cwcValue++;
XArray<WCHAR> wcsCopyOfValue( cwcValue ); RtlCopyMemory( wcsCopyOfValue.Get(), wcsValue, cwcValue * sizeof(WCHAR) );
PROPVARIANT propVariant; propVariant.vt = VT_LPWSTR; propVariant.pwszVal = wcsCopyOfValue.Get();
SetVariable( wcsName, &propVariant, ulCreateFlags | eParamOwnsVariantMemory );
wcsCopyOfValue.Acquire(); }
//+---------------------------------------------------------------------------
//
// Member: CVariableSet::AcquireStringValue - public
//
// Synopsis: A assignment operator; allows the value of a variable to
// be changed. Ownership of wcsValue is transferred.
//
// Arguments: [wcsName] - the variable name
// [wcsValue] - value of this variable
// [ulCreateFlags] - and flags associated with this variable;
//
// History: 96/Jan/03 DwightKr Created.
//
//----------------------------------------------------------------------------
void CVariableSet::AcquireStringValue( WCHAR const * wcsName, WCHAR * wcsValue, ULONG ulCreateFlags ) { Win4Assert( 0 != wcsName ); Win4Assert( 0 != wcsValue );
PROPVARIANT propVariant; propVariant.vt = VT_LPWSTR; propVariant.pwszVal = wcsValue;
SetVariable( wcsName, &propVariant, ulCreateFlags | eParamOwnsVariantMemory ); }
void CVariableSet::SetVariable( WCHAR const * wcsName, XArray<WCHAR> & xValue ) { Win4Assert( 0 != wcsName ); Win4Assert( 0 != xValue.Get() );
PROPVARIANT propVariant; propVariant.vt = VT_LPWSTR; propVariant.pwszVal = xValue.Get();
SetVariable( wcsName, &propVariant, eParamOwnsVariantMemory );
xValue.Acquire(); }
//+---------------------------------------------------------------------------
//
// Member: CVariableSet::AddVariableSet - public
//
// Synopsis: Adds all variables in the variableSet to this variableSet.
//
// Arguments: [variableSet] - the variableSet to add
//
// History: 96/Jan/03 DwightKr Created.
//
//----------------------------------------------------------------------------
void CVariableSet::AddVariableSet( CVariableSet & variableSet, COutputFormat & outputFormat ) { for ( CVariableSetIter iter(variableSet); !iter.AtEnd(); iter.Next() ) { CVariable * pVariable = iter.Get();
SetVariable( pVariable->GetName(), pVariable->GetValue(), pVariable->GetFlags() ); } }
//+---------------------------------------------------------------------------
//
// Member: CVariableSet::CVariableSet - copy constructor
//
// Synopsis: makes a copy of the variableSet
//
// Arguments: [variableSet] - the variableSet to copy
//
// History: 96/Jan/03 DwightKr Created.
// 96/Apr/11 DwightKr Set back link
//
//----------------------------------------------------------------------------
CVariableSet::CVariableSet( const CVariableSet & variableSet ) { RtlZeroMemory( _variableSet, sizeof _variableSet );
for ( CVariableSetIter iter(variableSet); !iter.AtEnd(); iter.Next() ) { CVariable * pVariable = iter.Get(); CVariable * pNewVariable = new CVariable( *pVariable );
XPtr<CVariable> xNewVariable(pNewVariable);
ULONG ulHash = ISAPIVariableNameHash( pNewVariable->GetName() );
//
// Set NEXT & BACK pointers in the hash chain
//
pNewVariable->SetNext( _variableSet[ ulHash ] ); if ( 0 != pNewVariable->GetNext() ) { pNewVariable->GetNext()->SetBack( pNewVariable ); }
_variableSet[ ulHash ] = pNewVariable;
xNewVariable.Acquire(); } }
//+---------------------------------------------------------------------------
//
// Member: CVariableSet::GetValue - public
//
// Synopsis: Gets the value of the variable whose name is specified.
//
// Arguments: [wcsName] - the variable name to return a value for
//
// Returns: PROPVARIANT * to the variable, 0 if no variable with this name.
//
// History: 96/Jan/03 DwightKr Created.
//
//----------------------------------------------------------------------------
PROPVARIANT * CVariableSet::GetValue( WCHAR const * wcsName ) const { CVariable * pVariable = Find( wcsName );
if ( pVariable ) return pVariable->GetValue(); else return 0; }
//+---------------------------------------------------------------------------
//
// Member: CVariableSet::GetStringValueRAW - public
//
// Synopsis: Gets the string value of the variable whose name is specified.
//
// Arguments: [wcsName] - the variable name to return a value for
//
// Returns: WCHAR * to the variable's string representation, 0 if no
// variable with this name.
//
// History: 96/Jan/03 DwightKr Created.
//
//----------------------------------------------------------------------------
WCHAR const * CVariableSet::GetStringValueRAW( WCHAR const * wcsName, ULONG ulHash, COutputFormat & outputFormat, ULONG & cwcValue ) { CVariable * pVariable = Find(wcsName, ulHash);
if ( pVariable ) return pVariable->GetStringValueRAW( outputFormat, cwcValue ); else return 0; }
//+---------------------------------------------------------------------------
//
// Member: CVariableSet::AddExtensionControlBlock
//
// Synopsis: Adds QUERY_STRING or STDIN buffer to variable set
//
// Arguments: [webServer] - extension control block to add to variableSet
//
// History: 03-Jan-96 DwightKr Created.
// 11-Jun-97 KyleP Take codepage from web server
// 11-Sep-98 KLam Assert that method is GET or POST
//
//----------------------------------------------------------------------------
void CVariableSet::AddExtensionControlBlock( CWebServer & webServer ) { //
// Determine if the user has passed the variables via a GET or POST
//
//
// We support only the GET and POST methods
//
BYTE * pszBuffer; ULONG cbBuffer;
XArray<BYTE> xTemp;
if ( strcmp( webServer.GetMethod(), "GET" ) == 0 ) { pszBuffer = (BYTE *) webServer.GetQueryString(); cbBuffer = strlen( (char *)pszBuffer ); } else if ( strcmp( webServer.GetMethod(), "POST" ) == 0 ) { pszBuffer = (BYTE *) webServer.GetClientData( cbBuffer );
// posts aren't null terminated, and we expect them to be.
xTemp.Init( cbBuffer + 1 ); RtlCopyMemory( xTemp.GetPointer(), pszBuffer, cbBuffer ); xTemp[cbBuffer] = 0; pszBuffer = xTemp.Get(); } else { //
// The validity of the method should have been checked before
//
Win4Assert ( strcmp( webServer.GetMethod(), "GET" ) == 0 || strcmp( webServer.GetMethod(), "POST" ) == 0); }
ciGibDebugOut(( DEB_ITRACE, "QUERY_STRING = %s\n", pszBuffer ));
// NOTE: The pszBuffer is pointing to strings in the ECB. We
// shouldn't modify these strings.
if ( cbBuffer > 0 ) { //
// Strip off trailing control characters, such as \n\r
//
while ( (cbBuffer > 0) && (pszBuffer[cbBuffer-1] <= ' ') ) { cbBuffer--; }
//
// Setup the QUERY_STRING variable in our variableSet
//
XArray<WCHAR> wcsQueryString; ULONG cwcBuffer = MultiByteToXArrayWideChar( (BYTE * const) pszBuffer, cbBuffer + 1, webServer.CodePage(), wcsQueryString );
Win4Assert( cwcBuffer != 0 && cwcBuffer <= (cbBuffer+1) ); wcsQueryString[ cwcBuffer ] = L'\0';
PROPVARIANT Variant; Variant.vt = VT_LPWSTR; Variant.pwszVal = wcsQueryString.Get(); SetVariable( ISAPI_QUERY_STRING, &Variant, eParamOwnsVariantMemory );
wcsQueryString.Acquire(); }
//
// Parse the string, which has the following format:
//
//
// attr1=Value1&attr2=value2&attr3=value+%7c+0&foo&bar
//
CHAR * pszToken = (CHAR *)pszBuffer; while ( (0 != pszToken) && (0 != *pszToken) ) { //
// Find the value on the right hand side of the equal sign.
//
CHAR *pszAttribute = pszToken; CHAR *pszValue = strchr( pszAttribute, '=' );
if ( 0 != pszValue ) { ULONG cchAttribute = (ULONG)(pszValue - pszAttribute); pszValue++;
// Point to the next attribute.
pszToken = strchr( pszToken, '&' );
ULONG cchValue;
if ( 0 != pszToken ) { if ( pszToken < pszValue ) { //
// We have a construction like foo&bar=value. Skip the
// 'foo' part.
//
pszToken++; continue; } cchValue = (ULONG)(pszToken - pszValue); pszToken++; } else { cchValue = (ULONG)((CHAR *)&pszBuffer[cbBuffer] - pszValue); }
WCHAR wcsAttribute[200]; if ( cchAttribute >= ( sizeof wcsAttribute / sizeof WCHAR ) ) THROW( CException( DB_E_ERRORSINCOMMAND ) );
DecodeURLEscapes( (BYTE *) pszAttribute, cchAttribute, wcsAttribute, webServer.CodePage() );
if ( 0 == cchAttribute ) THROW( CException( DB_E_ERRORSINCOMMAND ) );
DecodeHtmlNumeric( wcsAttribute );
//
// We could use Win32 for uppercasing the string, but we're looking for a fixed
// set of attributes that are known to be in this character set.
//
_wcsupr( wcsAttribute );
XArray<WCHAR> wcsValue( cchValue+2 );
DecodeURLEscapes( (BYTE *) pszValue, cchValue, wcsValue.Get(), webServer.CodePage() );
if ( 0 != cchValue ) { DecodeHtmlNumeric( wcsValue.Get() ); }
ciGibDebugOut(( DEB_ITRACE, "From browser, setting %ws=%ws\n", wcsAttribute, wcsValue.Get() ));
SetVariable( wcsAttribute, wcsValue ); } else { //
// There was an & and no =, so it looked like one of the following:
// &&&&&&&&&&&&&&&&&&&&&&&&&&&
// &asdfasdfasdfasdfasdfasdfas
// Most likely, this is a lame DOS attack. Just bail on it.
//
pszToken = 0; } } }
//+---------------------------------------------------------------------------
//
// Member: ISAPIVariableNameHash - public
//
// Synopsis: Generates a hash for the name specified
//
// Arguments: [pwcName] - the variable name to hash
//
// Returns: ULONG - hash of the name
//
// History: 96/Jan/03 DwightKr Created.
//
//
//----------------------------------------------------------------------------
ULONG ISAPIVariableNameHash( WCHAR const * pwcName ) { Win4Assert( 0 != pwcName ); WCHAR const *pwcStart = pwcName;
ULONG ulHash = 0;
while ( 0 != *pwcName ) { ulHash <<= 1; ulHash += *pwcName; pwcName++; }
ulHash <<= 1; ulHash += (ULONG)( pwcName - pwcStart );
return ulHash % VARIABLESET_HASH_TABLE_SIZE; }
//+---------------------------------------------------------------------------
//
// Member: CVariableSet::~CVariableSet - public
//
// Synopsis: Deletes the variables in the set.
//
// History: 96/Apr/03 dlee Created.
//
//
//----------------------------------------------------------------------------
CVariableSet::~CVariableSet() { // Variables delete the next in their chain, so only delete the
// start of each hash chain.
for ( unsigned x = 0; x < VARIABLESET_HASH_TABLE_SIZE; x++ ) delete _variableSet[ x ]; }
//+---------------------------------------------------------------------------
//
// Member: CVariableSet::Find
//
// Synopsis: Locates a variable in the variableSet with the given name
//
// Arguments: [wcsName] - name of variable to find
// [ulHash] - hashed value of the name
//
// Returns: pVariable if found, 0 otherwise
//
// History: 96/Apr/11 DwightKr Created.
//
//----------------------------------------------------------------------------
CVariable * CVariableSet::Find( WCHAR const * wcsName, ULONG ulHash ) const { Win4Assert( ulHash == ISAPIVariableNameHash(wcsName) );
//
// Walk down the chain and try to find a match
// Note: Variable names have been converted to upper case before
// we got this far. Hence, the case insensitive string
// comparison.
//
for ( CVariable * pVariable = _variableSet[ ulHash ]; pVariable != 0; pVariable = pVariable->GetNext() ) { Win4Assert( pVariable != 0);
if ( wcscmp(wcsName, pVariable->GetName() ) == 0 ) { return pVariable; } }
return 0; }
//+---------------------------------------------------------------------------
//
// Member: CVariableSet::Delete
//
// Synopsis: Deletes a single variable from a variableSet
//
// Arguments: [pVariable] - pointer to variable to delete
//
// History: 96/Apr/11 DwightKr Created.
//
//----------------------------------------------------------------------------
void CVariableSet::Delete( CVariable * pVariable ) { Win4Assert ( 0 != pVariable );
ULONG ulHash = ISAPIVariableNameHash( pVariable->GetName() ); Win4Assert( Find(pVariable->GetName(), ulHash) == pVariable );
//
// If there is a variable before this one in the hash chain, set its
// next pointer.
//
if ( 0 != pVariable->GetBack() ) { pVariable->GetBack()->SetNext( pVariable->GetNext() ); }
//
// If there is a variable after this one in the hash chain, set its
// back pointer.
//
if ( 0 != pVariable->GetNext() ) { pVariable->GetNext()->SetBack( pVariable->GetBack() ); }
//
// Update the array
//
if ( _variableSet[ulHash] == pVariable ) { _variableSet[ulHash] = pVariable->GetNext(); }
pVariable->SetNext(0); pVariable->SetBack(0);
delete pVariable; }
#if (DBG == 1)
//+---------------------------------------------------------------------------
//
// Member: CVariableSet::Dump
//
// Synopsis: Appends each of the variables to the virtual string supplied
//
// Arguments: [string] - string to append data to
//
// History: 96/Jan/03 DwightKr Created.
//
//----------------------------------------------------------------------------
void CVariableSet::Dump( CVirtualString & wcsString, COutputFormat & outputFormat ) { for (CVariableSetIter iter(*this); !iter.AtEnd(); iter.Next() ) { CVariable *pVariable = iter.Get();
wcsString.StrCat( pVariable->GetName() );
wcsString.CharCat( L'=' );
ULONG cwcValue; WCHAR * wcsValue = pVariable->GetStringValueRAW( outputFormat, cwcValue); wcsString.StrCat( wcsValue, cwcValue );
wcsString.StrCat( L"<BR>\n" ); } } #endif // DBG == 1
|