|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1994 - 1999
//
// File: tblvarnt.hxx
//
// Contents: Helper class for PROPVARIANTs in tables
//
// Classes: CTableVariant - PROPVARIANT wrapper; adds useful methods
//
// History: 28 Jan 1994 AlanW Created
//
//--------------------------------------------------------------------------
#pragma once
#include <tblalloc.hxx>
// A few useful defines and inline funcs.
#define BSTRLEN(bstrVal) *((ULONG *) bstrVal - 1)
inline BOOL IsLPWSTR(VARTYPE vt) { return VT_LPWSTR == vt;} inline BOOL IsLPSTR(VARTYPE vt) { return VT_LPSTR == vt;}
inline BOOL IsVector(VARTYPE vt) { return 0 != ( vt & VT_VECTOR );} inline BOOL IsArray(VARTYPE vt) { return 0 != ( vt & VT_ARRAY );} inline BOOL IsVectorOrArray(VARTYPE vt) { return 0 != ( vt & (VT_VECTOR | VT_ARRAY)); }
inline BOOL StatusSuccess(DBSTATUS status) { return (status == DBSTATUS_S_OK || status == DBSTATUS_S_ISNULL || status == DBSTATUS_S_TRUNCATED || status == DBSTATUS_S_DEFAULT); }
//+-------------------------------------------------------------------------
//
// Class: CTableVariant
//
// Purpose: Wraps PROPVARIANT struct, adding useful methods.
//
// Interface:
//
// Notes: Because the underlying base data *is* a variant, this
// class cannot have any non-static members (including
// a vtable).
//
// This class now deals only with PROPVARIANT. If conversion
// to other OLE-DB types or Automation variant types is needed,
// use COLEDBVaraint class (which derives from this class).
//
// The class is also used to extend the PROPVARIANT for use
// internally in tables. For internal storage, the
// PROPVARIANT.reserved2 field is used to store the total
// size of variable data pointed to by the variant.
// Also, the pointers within internal variants may
// be offsets to storage. There are three cases of
// the way offsets may be stored.
//
// The pointer inside the internal variant structure
// itself (to a vector, string, blob or UUID) is an
// offset based from the variable data allocator used
// to allocate the space.
//
// For vectors which contain pointers (e.g., vectors of
// strings), the pointers are stored as offsets based from
// the vector's address.
//
// For vectors of variants, the above two rules apply to
// each embedded variant. The rules apply recursively to
// embedded variants which are vectors of variant.
//
// Use of these rules permits the variable data of a variant
// to be treated as a unit and to be block copied from place
// to place without affecting the internally stored offsets.
//
// History: 21 Mar 1994 AlanW Created
// 09 Jan 1998 VikasMan Mofified the class to deal ONLY
// with PROPVARIANTs. Moved rest of
// the functionality in the
// COLEDBVaraiant class
// 01 Sep 1999 KLam Reinstated FixDataPointers used
// for Win64 Clients -> Win32 Servers
// 04 Nov 1999 KLam Added VarDataSize32
// for Win64 Servers -> Win32 Clients
//
//--------------------------------------------------------------------------
class CTableVariant: public tagPROPVARIANT {
public: //
// varntData is indexed by variant type, and gives the width,
// alignment constraints and other information for a scalar
// variant type.
//
struct VARNT_DATA { USHORT width; // width in bytes of data
USHORT alignment; // required alignment of data
USHORT flags; // flags about variants
}; static const VARNT_DATA varntData[], varntExtData[]; static const unsigned cVarntData, cVarntExtData;
#ifdef _WIN64
static const VARNT_DATA varntData32[], varntExtData32[]; #endif
enum varntDataFlags { CanBeVector = 1, // vector forms are permitted
ByRef = 2, // variant data has pointer to real data
CntRef = 4, // variant data has count followed by pointer
StoreDirect = 8, // variant form is indirect, store as fixed
MultiSize = 0x10, // used for chapters and bookmarks, for data
// like UI1 that is inline in client output
SimpleType = 0x20, // simple inline datatype, like VT_I4
OAType = 0x40, // valid type for automation VARIANT
};
static BOOL IsSimpleType( VARTYPE vtype ) { const VARNT_DATA & rvarInfo = _FindVarType( vtype );
return ( 0 != ( rvarInfo.flags & SimpleType ) ); }
static BOOL IsSimpleOAType( VARTYPE vtype ) { const VARNT_DATA & rvarInfo = _FindVarType( vtype );
return ( (SimpleType|OAType) == ( rvarInfo.flags & (SimpleType|OAType ) ) ); }
static BOOL CanBeVectorType( VARTYPE vtype ) { const VARNT_DATA & rvarInfo = _FindVarType( vtype );
return ( 0 != ( rvarInfo.flags & CanBeVector ) ); }
// NOTE: in NT5, VARIANT can include additional types. This operates on
// the traditional types so old clients can understand the variants
// we produce.
static BOOL IsOAType( VARTYPE vtype ) { const VARNT_DATA & rvarInfo = _FindVarType( vtype );
return ( 0 != ( rvarInfo.flags & OAType ) ); }
static BOOL IsByRef( VARTYPE vtype ) { const VARNT_DATA & rvarInfo = _FindVarType( vtype ); return ( 0 != ( rvarInfo.flags & ByRef ) ); }
//
// Return information about a variant's base type
//
static void VartypeInfo(VARTYPE vtype, USHORT& rcbWidth, USHORT& rcbAlign, USHORT& rgfFlags) { const VARNT_DATA& rvarInfo = _FindVarType(vtype);
rcbWidth = rvarInfo.width; rcbAlign = rvarInfo.alignment; rgfFlags = rvarInfo.flags;
if (vtype & VT_VECTOR) { rgfFlags |= CntRef; } return; }
//
// Check if a type is stored in-line in a table row.
//
static BOOL TableIsStoredInline( USHORT fFlags, VARTYPE vtype ) { if (vtype & (VT_ARRAY | VT_VECTOR | VT_BYREF) || vtype == VT_VARIANT || (fFlags & (CntRef | ByRef) && ! (fFlags & StoreDirect))) return FALSE;
return TRUE; }
static void Free(BYTE * pbData, VARTYPE vtData, PVarAllocator & rPool);
//
// Return TRUE iff the variant's type is valid for a property.
//
BOOL IsValidType(void) const { // NOTE: we don't expect VT_BYREF in our stored variants
if ( (vt & ~(VT_TYPEMASK | VT_VECTOR | VT_ARRAY)) != 0 || (vt & (VT_VECTOR | VT_ARRAY)) == (VT_VECTOR | VT_ARRAY) ) return FALSE;
const VARNT_DATA& rvarInfo = _FindVarType(vt);
if (vt & VT_VECTOR) return ((rvarInfo.flags & CanBeVector) == CanBeVector);
if (vt & VT_ARRAY) return ((rvarInfo.flags & (OAType|CanBeVector)) != 0);
return rvarInfo.width != 0; }
//
// Return TRUE iff the variant contains a pointer at offset 8
//
BOOL VariantPointerInFirstWord (void) const { return ( (vt & (VT_ARRAY | VT_BYREF)) != 0 || ( (vt & VT_VECTOR) == 0 && (_FindVarType(vt).flags & ByRef) == ByRef) ); // return ((vt == VT_CLSID) ||
// (vt == VT_LPWSTR) ||
// (vt == VT_LPSTR) ||
// (vt == VT_BSTR) ||
// (vt == VT_CF) ||
// (vt == VT_STREAM) ||
// (vt == VT_STREAMED_OBJECT) ||
// (vt == VT_STORAGE) ||
// (vt == VT_STORED_OBJECT));
}
//
// Return TRUE iff the variant contains a pointer at offset 0xC
//
BOOL VariantPointerInSecondWord (void) const { return ( (vt & VT_VECTOR) == VT_VECTOR || ( (vt & (VT_ARRAY | VT_BYREF)) == 0 && (_FindVarType(vt).flags & CntRef) == CntRef) ); }
//
// Copy data stored outside the variant structure itself
//
void Copy( CTableVariant* pvarntDest, PVarAllocator &rVarAllocator, USHORT cbDest, BYTE* pbBias = 0) const;
void OffsetsToPointers(PVarAllocator &rPool) { if ( VariantPointerInFirstWord() ) pszVal = (LPSTR) rPool.OffsetToPointer((ULONG_PTR) pszVal); else if ( VariantPointerInSecondWord() ) blob.pBlobData = (BYTE *) rPool.OffsetToPointer((ULONG_PTR) blob.pBlobData); }
DBSTATUS CopyOrCoerce( BYTE * pbDest, DBLENGTH cbDest, VARTYPE vtDest, DBLENGTH & rcbDstLen, PVarAllocator & rVarAllocator) const;
//
// Compute variable data size
//
ULONG VarDataSize (void) const;
#ifdef _WIN64
//
// Convert offsets to pointers in variable data (32server->64client)
//
void FixDataPointers( BYTE* pbBias, CFixedVarAllocator *pAlloc );
//
// Compute variable data size for 32 bit
//
ULONG VarDataSize32 ( BYTE *pbBase, ULONG_PTR ulpOffset ) const;
//
// Compute the size of a safearray for 32 bit
//
static ULONG SaComputeSize32 ( VARTYPE vt, SAFEARRAY & saSrc, BYTE *pbBase, ULONG_PTR ulpOffset );
//
// Return information about a variant's base type
//
static void VartypeInfo32( VARTYPE vtype, USHORT& rcbWidth, USHORT& rcbAlign, USHORT& rgfFlags) { const VARNT_DATA& rvarInfo = _FindVarType32(vtype);
rcbWidth = rvarInfo.width; rcbAlign = rvarInfo.alignment; rgfFlags = rvarInfo.flags;
if (vtype & VT_VECTOR) { rgfFlags |= CntRef; } return; }
#endif
//
// Initialize a variant from base parts
//
void Init( VARTYPE vt, BYTE* pbData = 0, ULONG cbData = 0);
protected: enum { ulCoercionCodePage = CP_ACP };
DBSTATUS _StoreString(BYTE * pbDstBuf, DBLENGTH cbDstBuf, VARTYPE vtDst, DBLENGTH & rcbDstLen, PVarAllocator & rPool) const;
DBSTATUS _StoreDecimal(DECIMAL * pDecimal, LONG lElem = 0) const;
DBSTATUS _StoreInteger(VARTYPE vtDst, BYTE * pbDstBuf, LONG lElem = 0) const; DBSTATUS _StoreIntegerUnSignedToSigned( VARTYPE vtDst, BYTE * pbDstBuf, LONG lElem = 0) const; DBSTATUS _StoreIntegerSignedToSigned( VARTYPE vtDst, BYTE * pbDstBuf, LONG lElem = 0) const; DBSTATUS _StoreIntegerUnSignedToUnSigned(VARTYPE vtDst, BYTE * pbDstBuf, LONG lElem = 0) const; DBSTATUS _StoreIntegerSignedToUnSigned( VARTYPE vtDst, BYTE * pbDstBuf, LONG lElem = 0) const;
private: void SetDataSize (ULONG cbVarData); void ResetDataSize ();
VOID * CopyData( PVarAllocator &rVarAllocator, USHORT cbDest, BYTE* pbBias = 0) const;
static const USHORT _wInternalSig; inline BOOL _IsInternalVariant( void ) const; static inline const VARNT_DATA& _FindVarType( VARTYPE vt );
#ifdef _WIN64
static inline const VARNT_DATA& _FindVarType32( VARTYPE vt ); #endif
DBSTATUS _GetUL8Value(ULONGLONG * ul8Value, LONG lElem = 0L) const; DBSTATUS _GetL8Value(LONGLONG * l8Value, LONG lElem = 0L ) const;
};
const USHORT minExtVariantType = 128;
#ifdef _WIN64
//+-------------------------------------------------------------------------
//
// Method: CTableVariant::_FindVarType32, inline private
//
// Synopsis: Return a 32 bit description of a variant given its type
//
// Arguments: [vt] - the variant type to be looked up
//
// Returns: VARNT_DATA& - a reference to the variant type information
//
//--------------------------------------------------------------------------
inline const CTableVariant::VARNT_DATA& CTableVariant::_FindVarType32( VARTYPE vtype ) { USHORT vtBase = vtype & VT_TYPEMASK;
if (vtBase < cVarntData) { return varntData32[vtBase]; } else if (vtBase >= minExtVariantType && vtBase < minExtVariantType + cVarntExtData) { return varntExtData32[ vtBase - minExtVariantType ]; } else { return varntData32[0]; // return ref. to VT_EMPTY info
} }
#endif // _WIN64
//+-------------------------------------------------------------------------
//
// Method: CTableVariant::_FindVarType, inline private
//
// Synopsis: Return a description of a variant given its type
//
// Arguments: [vt] - the variant type to be looked up
//
// Returns: VARNT_DATA& - a reference to the variant type information
//
//--------------------------------------------------------------------------
inline const CTableVariant::VARNT_DATA& CTableVariant::_FindVarType( VARTYPE vtype ) { USHORT vtBase = vtype & VT_TYPEMASK;
if (vtBase < cVarntData) { return varntData[vtBase]; } else if (vtBase >= minExtVariantType && vtBase < minExtVariantType + cVarntExtData) { return varntExtData[ vtBase - minExtVariantType ]; } else { return varntData[0]; // return ref. to VT_EMPTY info
} }
//+-------------------------------------------------------------------------
//
// Method: CTableVariant::_IsInternalVariant, inline private
//
// Synopsis: Return whether the variant is an internal form with
// pointers stored as offsets and variable data embedded.
//
// Arguments: -None-
//
// Returns: BOOL - TRUE if the variant is in internal form.
//
//--------------------------------------------------------------------------
inline BOOL CTableVariant::_IsInternalVariant( void ) const { return (wReserved1 == _wInternalSig && wReserved3 == _wInternalSig && VT_DECIMAL != vt); }
//+-------------------------------------------------------------------------
//
// Method: CTableVariant::SetDataSize, public
//
// Synopsis: Set variable data size for an internal variant
//
// Arguments: [cbVarData] - length of variable data associated with
// the variant.
//
// Returns: -Nothing-
//
// Notes: For variants which are stored internally in the table,
// the size is computed once and stored in the wReserved2
// field of the variant structure.
//
//--------------------------------------------------------------------------
inline void CTableVariant::SetDataSize (ULONG cbVarData) { Win4Assert(cbVarData <= USHRT_MAX);
if (vt != VT_DECIMAL) // this uses the reserved fields
{ wReserved2 = (USHORT)cbVarData;
//
// Put a signature value in the variant to distinguish internal
// vs. external variants.
//
wReserved1 = wReserved3 = _wInternalSig; } }
inline void CTableVariant::ResetDataSize () { if (vt != VT_DECIMAL) wReserved1 = wReserved2 = wReserved3 = 0; }
//+-------------------------------------------------------------------------
//
// Member: CTableVariant::_StoreDecimal, private
//
// Synopsis: Copy variant integer data, coercing to VT_DECIMAL
//
// Arguments: [pDec] -- destination buffer
// [lElem] -- element of vector to convert
//
// Returns: status for copy
//
// History: 25 Nov 1996 AlanW Created
//
//--------------------------------------------------------------------------
inline DBSTATUS CTableVariant::_StoreDecimal( DECIMAL * pDec, LONG lElem ) const { ULONGLONG ul8Value = 0;
Win4Assert( (vt & VT_TYPEMASK) != VT_DECIMAL );
DBSTATUS DstStatus = _GetUL8Value (&ul8Value, lElem);
if (DBSTATUS_S_OK == DstStatus) { pDec->scale = 0; pDec->sign = 0; pDec->Hi32 = 0; pDec->Lo64 = ul8Value; } else if ( DBSTATUS_E_CANTCONVERTVALUE == DstStatus ) { LONGLONG l8Value; DstStatus = _GetL8Value (&l8Value, lElem);
if (DBSTATUS_S_OK == DstStatus) { pDec->scale = 0; pDec->Hi32 = 0; if ( l8Value < 0 ) { pDec->sign = DECIMAL_NEG; pDec->Lo64 = -l8Value; } else { pDec->sign = 0; pDec->Lo64 = l8Value; } } }
return DstStatus; } //_StoreDecimal
//+-------------------------------------------------------------------------
//
// Member: CTableVariant::_StoreIntegerUnSignedToSigned, private
//
// Synopsis: Copy variant integer data, coerce if possible
//
// Arguments: [vtDst] -- type of the destination
// [pbDstBuf] -- destination buffer
// [lElem] -- element of vector to convert
//
// Returns: status for copy
//
// History: 24 Jul 1995 dlee Created
//
//--------------------------------------------------------------------------
inline DBSTATUS CTableVariant::_StoreIntegerUnSignedToSigned( VARTYPE vtDst, BYTE * pbDstBuf, LONG lElem ) const { ULONGLONG ul8Value = 0; DBSTATUS DstStatus = _GetUL8Value(&ul8Value, lElem);
// Store the ULONGLONG assuming alignment verified at accessor creation
if (DBSTATUS_S_OK == DstStatus) { switch ( vtDst ) { case VT_I1 : * (signed char *) pbDstBuf = (signed char) ul8Value; if ( ul8Value > SCHAR_MAX ) DstStatus = DBSTATUS_E_DATAOVERFLOW; break; case VT_I2 : * (short *) pbDstBuf = (short) ul8Value; if ( ul8Value > SHRT_MAX ) DstStatus = DBSTATUS_E_DATAOVERFLOW; break; case VT_I4 : case VT_INT : * (long *) pbDstBuf = (long) ul8Value; if ( ul8Value > LONG_MAX ) DstStatus = DBSTATUS_E_DATAOVERFLOW; break; case VT_I8 : * (LONGLONG *) pbDstBuf = (LONGLONG) ul8Value; if ( ul8Value > _I64_MAX ) DstStatus = DBSTATUS_E_DATAOVERFLOW; break; default: //tbDebugOut(( DEB_WARN, "US bad dst type %4x\n", vtDst ));
DstStatus = DBSTATUS_E_CANTCONVERTVALUE; break; } }
return DstStatus; } //_StoreIntegerUnSignedToSigned
//+-------------------------------------------------------------------------
//
// Member: CTableVariant::_StoreIntegerUnSignedToUnSigned, private
//
// Synopsis: Copy variant integer data, coerce if possible
//
// Arguments: [vtDst] -- type of the destination
// [pbDstBuf] -- destination buffer
// [lElem] -- element of vector to convert
//
// Returns: status for copy
//
// History: 24 Jul 1995 dlee Created
//
//--------------------------------------------------------------------------
inline DBSTATUS CTableVariant::_StoreIntegerUnSignedToUnSigned( VARTYPE vtDst, BYTE * pbDstBuf, LONG lElem ) const { ULONGLONG ul8Value; DBSTATUS DstStatus = _GetUL8Value(&ul8Value, lElem);
// Store the ULONGLONG assuming alignment verified at accessor creation
if (DBSTATUS_S_OK == DstStatus) { switch ( vtDst ) { case VT_UI1 : * (unsigned char *) pbDstBuf = (char) ul8Value; if ( ul8Value > UCHAR_MAX ) DstStatus = DBSTATUS_E_DATAOVERFLOW; break;
case VT_UI2 : * (unsigned short *) pbDstBuf = (unsigned short) ul8Value; if ( ul8Value > USHRT_MAX ) DstStatus = DBSTATUS_E_DATAOVERFLOW; break;
case VT_UI4 : case VT_UINT : * (unsigned long *) pbDstBuf = (unsigned long) ul8Value; if ( ul8Value > ULONG_MAX ) DstStatus = DBSTATUS_E_DATAOVERFLOW; break;
case VT_UI8 : * (ULONGLONG *) pbDstBuf = ul8Value; break;
default: //tbDebugOut(( DEB_WARN, "UU bad dst type %4x\n", vtDst ));
DstStatus = DBSTATUS_E_CANTCONVERTVALUE; break; } }
return DstStatus; } //_StoreIntegerUnSignedToUnSigned
//+-------------------------------------------------------------------------
//
// Member: CTableVariant::_StoreIntegerSignedToUnSigned, private
//
// Synopsis: Copy variant integer data, coerce if possible
//
// Arguments: [vtDst] -- type of the destination
// [pbDstBuf] -- destination buffer
// [lElem] -- element of vector to convert
//
// Returns: status for copy
//
// History: 24 Jul 1995 dlee Created
//
//--------------------------------------------------------------------------
inline DBSTATUS CTableVariant::_StoreIntegerSignedToUnSigned( VARTYPE vtDst, BYTE * pbDstBuf, LONG lElem ) const { LONGLONG l8Value; DBSTATUS DstStatus = _GetL8Value( &l8Value, lElem ) ;
// Store the LONGLONG assuming alignment verified at accessor creation
if (DBSTATUS_S_OK == DstStatus) { if ( l8Value < 0 ) DstStatus = DBSTATUS_E_SIGNMISMATCH; else { switch ( vtDst ) { case VT_UI1 : * (unsigned char *) pbDstBuf = (unsigned char) l8Value; if ( l8Value > UCHAR_MAX ) DstStatus = DBSTATUS_E_DATAOVERFLOW; break; case VT_UI2 : * (unsigned short *) pbDstBuf = (unsigned short) l8Value; if ( l8Value > USHRT_MAX ) DstStatus = DBSTATUS_E_DATAOVERFLOW; break; case VT_UI4 : case VT_UINT : * (unsigned long *) pbDstBuf = (unsigned long) l8Value; if ( l8Value > ULONG_MAX ) DstStatus = DBSTATUS_E_DATAOVERFLOW; break; case VT_UI8 : * (ULONGLONG *) pbDstBuf = (ULONGLONG) l8Value; break; default: //tbDebugOut(( DEB_WARN, "SU bad dst type %4x\n", vtDst ));
DstStatus = DBSTATUS_E_CANTCONVERTVALUE; break; } } }
return DstStatus; } //_StoreIntegerSignedToUnSigned
//+-------------------------------------------------------------------------
//
// Member: CTableVariant::_StoreIntegerSignedToSigned, private
//
// Synopsis: Copy variant integer data, coerce if possible
//
// Arguments: [vtDst] -- type of the destination
// [pbDstBuf] -- destination buffer
// [lElem] -- element of vector to convert
//
// Returns: status for copy
//
// History: 24 Jul 1995 dlee Created
//
//--------------------------------------------------------------------------
inline DBSTATUS CTableVariant::_StoreIntegerSignedToSigned( VARTYPE vtDst, BYTE * pbDstBuf, LONG lElem ) const { LONGLONG l8Value = 0; DBSTATUS DstStatus = _GetL8Value ( &l8Value, lElem );
// Store the ULONGLONG assuming alignment verified at accessor creation
if (DBSTATUS_S_OK == DstStatus) { switch ( vtDst ) { case VT_I1 : * (signed char *) pbDstBuf = (signed char) l8Value; if (l8Value < SCHAR_MIN || l8Value > SCHAR_MAX) DstStatus = DBSTATUS_E_DATAOVERFLOW; break; case VT_I2 : * (short *) pbDstBuf = (short) l8Value; if (l8Value < SHRT_MIN || l8Value > SHRT_MAX) DstStatus = DBSTATUS_E_DATAOVERFLOW; break; case VT_I4 : * (long *) pbDstBuf = (long) l8Value; if (l8Value < LONG_MIN || l8Value > LONG_MAX) DstStatus = DBSTATUS_E_DATAOVERFLOW; break; case VT_I8 : * (LONGLONG *) pbDstBuf = l8Value; break; default: //tbDebugOut(( DEB_WARN, "SS bad dst type %4x\n", vtDst ));
DstStatus = DBSTATUS_E_CANTCONVERTVALUE; break; } }
return DstStatus; } //_StoreIntegerSignedToSigned
//+-------------------------------------------------------------------------
//
// Member: CTableVariant::_StoreInteger, private
//
// Synopsis: Copy variant integer data, coerce if possible
//
// Arguments: [vtDst] -- type of the destination
// [pbDstBuf] -- destination buffer
// [lElem] -- element of vector to convert
//
// Returns: status for copy
//
// History: 24 Jul 1995 dlee Rewrote to support unsigned values
//
//--------------------------------------------------------------------------
inline BOOL isSignedInteger( VARTYPE vt ) { return ( VT_I1 == vt || VT_I2 == vt || VT_I4 == vt || VT_INT == vt || VT_I8 == vt || VT_BOOL == vt ); } //isSignedInteger
inline DBSTATUS CTableVariant::_StoreInteger( VARTYPE vtDst, BYTE * pbDstBuf, LONG lElem ) const { // vt is the type of the source of the data
Win4Assert( vt == VT_I1 || vt == VT_UI1 || vt == VT_I2 || vt == VT_UI2 || vt == VT_I4 || vt == VT_UI4 || vt == VT_I8 || vt == VT_UI8 || vt == VT_INT || vt == VT_UINT || vt == VT_BOOL || vt == VT_ERROR || vt == VT_HRESULT || vt == VT_FILETIME || vt == VT_EMPTY || // empty if object is deleted
vt == (VT_I1 | VT_VECTOR) || vt == (VT_UI1 | VT_VECTOR) || vt == (VT_I2 | VT_VECTOR) || vt == (VT_UI2 | VT_VECTOR) || vt == (VT_I4 | VT_VECTOR) || vt == (VT_UI4 | VT_VECTOR) || vt == (VT_I8 | VT_VECTOR) || vt == (VT_UI8 | VT_VECTOR) || vt == (VT_BOOL | VT_VECTOR) || vt == (VT_ERROR | VT_VECTOR) || vt == (VT_FILETIME | VT_VECTOR));
BOOL fSrcSigned = isSignedInteger( vt & VT_TYPEMASK ); BOOL fDstSigned = isSignedInteger( vtDst );
if ( fSrcSigned && fDstSigned ) return _StoreIntegerSignedToSigned( vtDst, pbDstBuf, lElem ); else if ( fSrcSigned && !fDstSigned ) return _StoreIntegerSignedToUnSigned( vtDst, pbDstBuf, lElem ); else if ( !fSrcSigned && fDstSigned ) return _StoreIntegerUnSignedToSigned( vtDst, pbDstBuf, lElem ); else return _StoreIntegerUnSignedToUnSigned( vtDst, pbDstBuf, lElem );
} //_StoreInteger
//+-------------------------------------------------------------------------
//
// Method: CTableVariant::_GetL8Value, private
//
// Synopsis: Converts the variant value to a LONGLONG
//
// Arguments: [*l8Value] - LONGLONG value on return
// [lElem] - for vector variants, the element whose value is
// to be converted
//
// Returns: DBSTATUS
//
//--------------------------------------------------------------------------
inline DBSTATUS CTableVariant::_GetL8Value(LONGLONG * l8Value, LONG lElem ) const { *l8Value = 0; DBSTATUS DstStatus = DBSTATUS_S_OK;
Win4Assert((lElem == 0) || (vt & DBTYPE_VECTOR));
switch ( vt ) // type of the source
{ case VT_I1: *l8Value = (CHAR)bVal; break;
case VT_I2: case VT_BOOL: *l8Value = iVal; break;
case VT_I4: case VT_INT : *l8Value = lVal; break;
case VT_I8: *l8Value = hVal.QuadPart; break;
case VT_EMPTY: case VT_NULL : DstStatus = DBSTATUS_S_ISNULL; break;
case VT_I1 | VT_VECTOR: // no i1 vector struct definition use UI1 and cast
*l8Value = (CHAR)caub.pElems[lElem]; break;
case VT_I2 | VT_VECTOR: *l8Value = cai.pElems[lElem]; break;
case VT_I4 | VT_VECTOR: *l8Value = cal.pElems[lElem]; break;
case VT_I8 | VT_VECTOR: *l8Value = cah.pElems[lElem].QuadPart; break;
default: //tbDebugOut(( DEB_WARN, "_GetL8Value bad src type %4x\n", vt ));
DstStatus = DBSTATUS_E_CANTCONVERTVALUE; break; } return DstStatus; }
//+-------------------------------------------------------------------------
//
// Method: CTableVariant::_GetUL8Value, private
//
// Synopsis: Converts the variant value to a ULONGLONG
//
// Arguments: [*ul8Value] - ULONGLONG value on return
// [lElem] - for vector variants, the element whose value is
// to be converted
//
// Returns: DBSTATUS
//
//--------------------------------------------------------------------------
inline DBSTATUS CTableVariant::_GetUL8Value(ULONGLONG * ul8Value, LONG lElem ) const { *ul8Value = 0; DBSTATUS DstStatus = DBSTATUS_S_OK;
Win4Assert((lElem == 0) || (vt & DBTYPE_VECTOR));
switch ( vt ) // type of the source
{ case VT_UI1: *ul8Value = bVal; break;
case VT_UI2: *ul8Value = uiVal; break;
case VT_UI4: case VT_UINT : case VT_ERROR : case VT_HRESULT : *ul8Value = ulVal; break;
case VT_UI8: case VT_FILETIME : *ul8Value = uhVal.QuadPart; break;
case VT_EMPTY: case VT_NULL : DstStatus = DBSTATUS_S_ISNULL; break;
case VT_UI1 | VT_VECTOR: *ul8Value = caub.pElems[lElem]; break;
case VT_UI2 | VT_VECTOR: *ul8Value = caui.pElems[lElem]; break;
case VT_BOOL | VT_VECTOR : *ul8Value = cabool.pElems[lElem]; break;
case VT_UI4 | VT_VECTOR: *ul8Value = caul.pElems[lElem]; break;
case VT_ERROR | VT_VECTOR: *ul8Value = cascode.pElems[lElem]; break;
case VT_UI8 | VT_VECTOR: *ul8Value = cauh.pElems[lElem].QuadPart; break;
case VT_FILETIME | VT_VECTOR: *ul8Value = ((ULARGE_INTEGER *)(&cafiletime.pElems[lElem]))->QuadPart; break;
default: //tbDebugOut(( DEB_WARN, "_GetUL8Value bad src type %4x\n", vt ));
DstStatus = DBSTATUS_E_CANTCONVERTVALUE; break; } return DstStatus;
}
|