#pragma once
#ifndef __HWINVARIANT_H__
#define __HWINVARIANT_H__
#include "hwindef.h"
#include "hwincom.h"
#include "hwinexception.h"
#include "hwindatetime.h"
namespace harlinn
{
namespace windows
{
// ----------------------------------------------------------------------
// VariantType
// ----------------------------------------------------------------------
enum class VariantType : unsigned short
{
Empty = 0,
Null = 1,
Int2 = 2,
Short = 2,
Int4 = 3,
Long = 3,
Real4 = 4,
Float = 4,
Real8 = 5,
Double = 5,
Currency = 6,
DateTime = 7,
BStr = 8,
Dispatch = 9,
Error = 10,
Bool = 11,
Variant = 12,
Unknown = 13,
Decimal = 14,
Int1 = 16,
SByte = 16,
UInt1 = 17,
Byte = 17,
UInt2 = 18,
UShort = 18,
UInt4 = 19,
ULong = 19,
Int8 = 20,
Int64 = 20,
LongLong = 20,
UInt8 = 21,
UInt64 = 21,
ULongLong = 21,
Int = 22,
UInt = 23,
Void = 24,
HResult = 25,
Pointer = 26,
SafeArray = 27,
CArray = 28,
UserDefined = 29,
LPStr = 30,
LPWStr = 31,
Record = 36,
IntPtr = 37,
UIntPtr = 38,
FileTime = 64,
Blob = 65,
Stream = 66,
Storage = 67,
StreamedObject = 68,
StoredObject = 69,
BlobObject = 70,
CF = 71,
CLSID = 72,
VersionedStream = 73,
BStrBlob = 0xfff,
Vector = 0x1000,
Array = 0x2000,
Byref = 0x4000,
Reserved = 0x8000,
Illegal = 0xffff,
IllegalMasked = 0xfff,
TypeMask = 0xfff
};
DEFINE_ENUM_FLAG_OPERATORS( VariantType )
// ----------------------------------------------------------------------
// SysString
// ----------------------------------------------------------------------
class SysString
{
BSTR bstr;
public:
static BSTR Copy( const BSTR bstr )
{
if ( bstr )
{
UINT length = SysStringLen( bstr );
auto result = SysAllocStringLen( bstr, length );
if ( ( !result ) && length )
{
CheckHRESULT( E_OUTOFMEMORY );
}
return result;
}
return nullptr;
}
SysString( )
: bstr( 0 )
{
}
SysString( const WideString& theString )
: bstr( 0 )
{
bstr = SysAllocStringLen( theString.c_str( ), UINT( theString.length( ) ) );
if ( ( bstr == nullptr ) && ( theString.length( ) ) )
{
CheckHRESULT( E_OUTOFMEMORY );
}
}
SysString( const wchar_t* theString, bool attach = false )
: bstr( 0 )
{
if ( !attach )
{
bstr = SysAllocString( theString );
if ( ( bstr == nullptr ) && theString && theString[0] )
{
CheckHRESULT( E_OUTOFMEMORY );
}
}
else
{
bstr = ( BSTR )theString;
}
}
SysString( const wchar_t* theString, size_t theLength )
: bstr( 0 )
{
bstr = SysAllocStringLen( theString, UINT( theLength ) );
if ( ( bstr == nullptr ) && theString && theString[0] )
{
CheckHRESULT( E_OUTOFMEMORY );
}
}
SysString( const SysString& other )
: bstr( Copy( other.bstr ) )
{
}
SysString( SysString&& other )
: bstr( other.bstr )
{
other.bstr = nullptr;
}
~SysString( )
{
if ( bstr )
{
SysFreeString( bstr );
}
}
SysString& operator = ( const SysString& other )
{
if ( bstr != other.bstr )
{
if ( bstr )
{
SysFreeString( bstr );
bstr = nullptr;
}
bstr = Copy( other.bstr );
}
return *this;
}
SysString& operator = ( SysString&& other )
{
if ( this != &other )
{
if ( bstr )
{
SysFreeString( bstr );
bstr = nullptr;
}
bstr = other.bstr;
other.bstr = nullptr;
}
return *this;
}
SysString& Attach( BSTR theString )
{
if ( bstr != theString )
{
if ( bstr )
{
SysFreeString( bstr );
bstr = nullptr;
}
bstr = theString;
}
return *this;
}
BSTR Detach( )
{
auto result = bstr;
bstr = nullptr;
return result;
}
BSTR Copy( ) const
{
return Copy( bstr );
}
const BSTR c_str( ) const
{
return bstr;
}
BSTR c_str( )
{
return bstr;
}
size_t length( ) const
{
if ( bstr )
{
return size_t( SysStringLen( bstr ) );
}
return 0;
}
OLECHAR At( size_t index ) const
{
return bstr[index];
}
OLECHAR& At( size_t index )
{
return bstr[index];
}
OLECHAR operator []( size_t index ) const
{
return bstr[index];
}
OLECHAR& operator []( size_t index )
{
return bstr[index];
}
};
// ----------------------------------------------------------------------
// SafeArray
// ----------------------------------------------------------------------
class SafeArray
{
SAFEARRAY* ptr;
public:
static VariantType GetElementVariantType( SAFEARRAY* safeArray )
{
if ( safeArray )
{
if ( safeArray->fFeatures & FADF_DISPATCH )
{
return VariantType::Dispatch;
}
if ( safeArray->fFeatures & FADF_UNKNOWN )
{
return VariantType::Unknown;
}
if ( safeArray->fFeatures & FADF_VARIANT )
{
return VariantType::Variant;
}
if ( safeArray->fFeatures & FADF_BSTR )
{
return VariantType::BStr;
}
VARTYPE vt = 0;
auto hr = SafeArrayGetVartype( safeArray, &vt );
if ( FAILED( hr ) )
{
CheckHRESULT( hr );
}
}
else
{
return VariantType::Empty;
}
}
// ----------------------------------------------------------------------
// Lock
// ----------------------------------------------------------------------
friend class SafeArrayLock;
class SafeArrayLock
{
SAFEARRAY* safeArray;
public:
SafeArrayLock( SafeArray& theSafeArray )
{
safeArray = theSafeArray.ptr;
auto hr = ::SafeArrayLock( safeArray );
if ( FAILED( hr ) )
{
CheckHRESULT( hr );
}
}
~SafeArrayLock( )
{
if ( safeArray )
{
SafeArrayUnlock( safeArray );
}
}
};
typedef SafeArrayLock Lock;
// ----------------------------------------------------------------------
// DataLock
// ----------------------------------------------------------------------
class DataLock
{
SAFEARRAY* safeArray;
void* data;
public:
DataLock( SafeArray& theSafeArray )
{
safeArray = theSafeArray.ptr;
auto hr = SafeArrayAccessData( safeArray, &data );
if ( FAILED( hr ) )
{
CheckHRESULT( hr );
}
}
~DataLock( )
{
if ( safeArray )
{
SafeArrayUnaccessData( safeArray );
}
}
template<typename T>
T* Data( )
{
return reinterpret_cast<T*>( data );
}
};
SafeArray( )
: ptr( 0 )
{
}
SafeArray( VariantType variantType, UINT numberOfElements )
: ptr( 0 )
{
SAFEARRAYBOUND rgsabound = { numberOfElements, 0 };
ptr = SafeArrayCreate( VARTYPE( variantType ), 1, &rgsabound );
if ( !ptr )
{
CheckHRESULT( E_OUTOFMEMORY );
}
}
SafeArray( const SafeArray& other )
: ptr( 0 )
{
if ( other.ptr )
{
auto hr = SafeArrayCopy( other.ptr, &ptr );
if ( FAILED( hr ) )
{
CheckHRESULT( hr );
}
}
}
SafeArray( SafeArray&& other )
: ptr( other.ptr )
{
other.ptr = nullptr;
}
~SafeArray( )
{
if ( ptr )
{
auto hr = SafeArrayDestroy( ptr );
CheckHRESULT( hr );
}
}
SafeArray& operator = ( const SafeArray& other )
{
if ( other.ptr && ( ptr != other.ptr ) )
{
if ( ptr )
{
auto hr = SafeArrayDestroy( ptr );
CheckHRESULT( hr );
ptr = nullptr;
}
auto hr = SafeArrayCopy( other.ptr, &ptr );
if ( FAILED( hr ) )
{
CheckHRESULT( hr );
}
}
return *this;
}
SafeArray& operator = ( SafeArray&& other )
{
if ( this != &other )
{
if ( ptr )
{
auto hr = SafeArrayDestroy( ptr );
CheckHRESULT( hr );
ptr = nullptr;
}
ptr = other.ptr;
other.ptr = nullptr;
}
return *this;
}
};
// ----------------------------------------------------------------------
// Variant
// ----------------------------------------------------------------------
class Variant : public VARIANT
{
void SetVariantType( VariantType variantType )
{
vt = USHORT( variantType );
}
public:
static int Compare( const VARIANT& first, const VARIANT& second )
{
if ( first.vt == USHORT( VariantType::Empty ) )
{
if ( second.vt == USHORT( VariantType::Empty ) )
{
return 0;
}
return -1;
}
else if ( second.vt == USHORT( VariantType::Empty ) )
{
return 1;
}
else if ( first.vt == USHORT( VariantType::Null ) )
{
if ( second.vt == USHORT( VariantType::Null ) )
{
return 0;
}
return -1;
}
else if ( second.vt == USHORT( VariantType::Null ) )
{
return 1;
}
auto lcid = GetUserDefaultLCID( );
auto result = VarCmp( ( VARIANT* )&first, ( VARIANT* )&second, lcid );
if ( FAILED( result ) )
{
CheckHRESULT( result );
}
return result - 1;
}
VariantType Type( ) const
{
return VariantType( vt );
}
VariantType ElementType( ) const
{
return VariantType( vt & VT_TYPEMASK );
}
bool IsEmpty( ) const
{
return Type( ) == VariantType::Empty;
}
bool IsNull( ) const
{
return Type( ) == VariantType::Null;
}
bool IsReference( ) const
{
return ( Type( ) & VariantType::Byref ) != VariantType::Empty;
}
bool IsArray( ) const
{
return ( Type( ) & VariantType::Array ) != VariantType::Empty;
}
Variant( )
{
SetVariantType( VariantType::Empty );
}
Variant( long long theValue )
{
SetVariantType( VariantType::Int64 );
llVal = theValue;
}
Variant( unsigned long long theValue )
{
SetVariantType( VariantType::UInt64 );
ullVal = theValue;
}
Variant( LONG theValue )
{
SetVariantType( VariantType::Long );
lVal = theValue;
}
Variant( LONG theValue, VariantType variantType )
{
if ( variantType == VariantType::Long || variantType == VariantType::Error )
{
SetVariantType( variantType );
lVal = theValue;
}
else
{
SetVariantType( VariantType::Error );
scode = E_INVALIDARG;
CheckHRESULT( scode );
}
}
Variant( BYTE theValue )
{
SetVariantType( VariantType::Byte );
bVal = theValue;
}
Variant( SHORT theValue )
{
SetVariantType( VariantType::Short );
iVal = theValue;
}
Variant( FLOAT theValue )
{
SetVariantType( VariantType::Float );
fltVal = theValue;
}
Variant( DOUBLE theValue )
{
SetVariantType( VariantType::Double );
dblVal = theValue;
}
Variant( DOUBLE theValue, VariantType variantType )
{
if ( variantType == VariantType::Double || variantType == VariantType::DateTime )
{
SetVariantType( variantType );
dblVal = theValue;
}
else
{
SetVariantType( VariantType::Error );
scode = E_INVALIDARG;
CheckHRESULT( scode );
}
}
Variant( bool theValue )
{
SetVariantType( VariantType::Bool );
boolVal = theValue ? VARIANT_TRUE : VARIANT_FALSE;
}
Variant( const CY& theValue )
{
SetVariantType( VariantType::Currency );
cyVal = theValue;
}
Variant( const DateTime& theValue )
{
SetVariantType( VariantType::DateTime );
date = theValue.ToOADate( );
}
Variant( const TimeSpan& theValue )
{
SetVariantType( VariantType::DateTime );
date = theValue.TotalDays( );
}
Variant( const SysString& theValue )
{
SetVariantType( VariantType::BStr );
bstrVal = theValue.Copy( );
}
Variant( const WideString& theValue )
{
SetVariantType( VariantType::BStr );
bstrVal = nullptr;
if ( theValue.length( ) )
{
bstrVal = SysAllocStringLen( theValue.c_str( ), UINT( theValue.length( ) ) );
if ( !bstrVal )
{
CheckHRESULT( E_OUTOFMEMORY );
}
}
}
Variant( IUnknown* pInterface )
{
SetVariantType( VariantType::Unknown );
punkVal = pInterface;
if ( punkVal )
{
punkVal->AddRef( );
}
}
Variant( IDispatch* pInterface )
{
SetVariantType( VariantType::Dispatch );
pdispVal = pInterface;
if ( pdispVal )
{
pdispVal->AddRef( );
}
}
Variant( SAFEARRAY* safeArray )
{
SetVariantType( VariantType::Array );
if ( safeArray )
{
auto vType = SafeArray::GetElementVariantType( safeArray );
SetVariantType( VariantType::Array | vType );
auto hr = SafeArrayCopy( safeArray, &parray );
CheckHRESULT( hr );
}
else
{
parray = nullptr;
}
}
Variant( CHAR theValue )
{
SetVariantType( VariantType::SByte );
cVal = theValue;
}
Variant( USHORT theValue )
{
SetVariantType( VariantType::UShort );
uiVal = theValue;
}
Variant( ULONG theValue )
{
SetVariantType( VariantType::ULong );
ulVal = theValue;
}
Variant( const Variant& other )
{
VariantInit( this );
auto hr = VariantCopy( this, &other );
CheckHRESULT( hr );
}
Variant( Variant&& other )
{
memcpy( &vt, &other.vt, sizeof( VARIANT ) );
memset( &other.vt, 0, sizeof( VARIANT ) );
}
Variant& Clear( )
{
switch ( vt )
{
case VT_EMPTY:
case VT_NULL:
case VT_I1:
case VT_I2:
case VT_I4:
case VT_I8:
case VT_UI1:
case VT_UI2:
case VT_UI4:
case VT_UI8:
case VT_R4:
case VT_R8:
case VT_CY:
case VT_DATE:
vt = VT_EMPTY;
break;
default:
auto hr = VariantClear( this );
CheckHRESULT( hr );
break;
}
return *this;
}
~Variant( )
{
if ( vt != VT_EMPTY )
{
Clear( );
}
}
Variant& operator = ( const Variant& other )
{
if ( &vt != &other.vt )
{
if ( vt != VT_EMPTY )
{
auto hr = VariantClear( this );
CheckHRESULT( hr );
}
auto hr = VariantCopy( this, &other );
CheckHRESULT( hr );
}
return *this;
}
Variant& operator = ( Variant&& other )
{
if ( this != &other )
{
if ( vt != VT_EMPTY )
{
auto hr = VariantClear( this );
CheckHRESULT( hr );
}
memcpy( &vt, &other.vt, sizeof( VARIANT ) );
memset( &other.vt, 0, sizeof( VARIANT ) );
}
return *this;
}
int CompareTo( const VARIANT& other ) const
{
return Compare( *this, other );
}
int CompareTo( const Variant& other ) const
{
return Compare( *this, other );
}
bool operator == ( const VARIANT& other ) const
{
return CompareTo( other ) == 0;
}
bool operator != ( const VARIANT& other ) const
{
return CompareTo( other ) != 0;
}
bool operator <= ( const VARIANT& other ) const
{
return CompareTo( other ) <= 0;
}
bool operator < ( const VARIANT& other ) const
{
return CompareTo( other ) < 0;
}
bool operator > ( const VARIANT& other ) const
{
return CompareTo( other ) > 0;
}
bool operator >= ( const VARIANT& other ) const
{
return CompareTo( other ) >= 0;
}
bool operator == ( const Variant& other ) const
{
return CompareTo( other ) == 0;
}
bool operator != ( const Variant& other ) const
{
return CompareTo( other ) != 0;
}
bool operator <= ( const Variant& other ) const
{
return CompareTo( other ) <= 0;
}
bool operator < ( const Variant& other ) const
{
return CompareTo( other ) < 0;
}
bool operator > ( const Variant& other ) const
{
return CompareTo( other ) > 0;
}
bool operator >= ( const Variant& other ) const
{
return CompareTo( other ) >= 0;
}
HRESULT AssignTo( VARIANT& other ) const
{
HRESULT result = S_OK;
if ( other.vt != VT_EMPTY )
{
result = VariantClear( &other );
if ( FAILED( result ) )
{
return result;
}
other.vt = VT_EMPTY;
}
if ( IsEmpty( ) == FALSE )
{
result = VariantCopy( &other, this );
}
return result;
}
Variant& Assign( long long theValue )
{
Clear( );
SetVariantType( VariantType::Int64 );
llVal = theValue;
return *this;
}
Variant& Assign( unsigned long long theValue )
{
Clear( );
SetVariantType( VariantType::UInt64 );
ullVal = theValue;
return *this;
}
Variant& Assign( LONG theValue )
{
Clear( );
SetVariantType( VariantType::Long );
lVal = theValue;
return *this;
}
Variant& Assign( LONG theValue, VariantType variantType )
{
Clear( );
if ( variantType == VariantType::Long || variantType == VariantType::Error )
{
SetVariantType( variantType );
lVal = theValue;
}
else
{
SetVariantType( VariantType::Error );
scode = E_INVALIDARG;
CheckHRESULT( scode );
}
return *this;
}
Variant& Assign( BYTE theValue )
{
Clear( );
SetVariantType( VariantType::Byte );
bVal = theValue;
return *this;
}
Variant& Assign( SHORT theValue )
{
Clear( );
SetVariantType( VariantType::Short );
iVal = theValue;
return *this;
}
Variant& Assign( FLOAT theValue )
{
Clear( );
SetVariantType( VariantType::Float );
fltVal = theValue;
return *this;
}
Variant& Assign( DOUBLE theValue )
{
Clear( );
SetVariantType( VariantType::Double );
dblVal = theValue;
return *this;
}
Variant& Assign( DOUBLE theValue, VariantType variantType )
{
Clear( );
if ( variantType == VariantType::Double || variantType == VariantType::DateTime )
{
SetVariantType( variantType );
dblVal = theValue;
}
else
{
SetVariantType( VariantType::Error );
scode = E_INVALIDARG;
CheckHRESULT( scode );
}
return *this;
}
Variant& Assign( bool theValue )
{
Clear( );
SetVariantType( VariantType::Bool );
boolVal = theValue ? VARIANT_TRUE : VARIANT_FALSE;
return *this;
}
Variant& Assign( const CY& theValue )
{
Clear( );
SetVariantType( VariantType::Currency );
cyVal = theValue;
return *this;
}
Variant& Assign( const DateTime& theValue )
{
Clear( );
SetVariantType( VariantType::DateTime );
date = theValue.ToOADate( );
return *this;
}
Variant& Assign( const TimeSpan& theValue )
{
Clear( );
SetVariantType( VariantType::Double );
date = theValue.TotalDays( );
return *this;
}
Variant& Assign( const SysString& theValue )
{
Clear( );
SetVariantType( VariantType::BStr );
bstrVal = theValue.Copy( );
return *this;
}
Variant& Assign( const WideString& theValue )
{
Clear( );
SetVariantType( VariantType::BStr );
bstrVal = nullptr;
if ( theValue.length( ) )
{
bstrVal = SysAllocStringLen( theValue.c_str( ), UINT( theValue.length( ) ) );
if ( !bstrVal )
{
CheckHRESULT( E_OUTOFMEMORY );
}
}
return *this;
}
Variant& Assign( IUnknown* pInterface )
{
Clear( );
SetVariantType( VariantType::Unknown );
punkVal = pInterface;
if ( punkVal )
{
punkVal->AddRef( );
}
return *this;
}
Variant& Assign( IDispatch* pInterface )
{
Clear( );
SetVariantType( VariantType::Dispatch );
pdispVal = pInterface;
if ( pdispVal )
{
pdispVal->AddRef( );
}
return *this;
}
Variant& Assign( SAFEARRAY* safeArray )
{
Clear( );
SetVariantType( VariantType::Array );
if ( safeArray )
{
auto vType = SafeArray::GetElementVariantType( safeArray );
SetVariantType( VariantType::Array | vType );
auto hr = SafeArrayCopy( safeArray, &parray );
CheckHRESULT( hr );
}
else
{
parray = nullptr;
}
return *this;
}
Variant& Assign( CHAR theValue )
{
Clear( );
SetVariantType( VariantType::SByte );
cVal = theValue;
return *this;
}
Variant& Assign( USHORT theValue )
{
Clear( );
SetVariantType( VariantType::UShort );
uiVal = theValue;
return *this;
}
Variant& Assign( ULONG theValue )
{
Clear( );
SetVariantType( VariantType::ULong );
ulVal = theValue;
return *this;
}
template <typename T>
Variant& operator = ( const T& theValue )
{
return Assign( theValue );
}
bool AsBoolean( ) const
{
switch ( Type( ) )
{
case VariantType::Empty:
return false;
break;
case VariantType::Null:
return false;
break;
case VariantType::Bool:
return boolVal != VARIANT_FALSE;
break;
case VariantType::Int1:
return cVal != 0;
break;
case VariantType::UInt1:
return bVal != 0;
break;
case VariantType::Int2:
return iVal != 0;
break;
case VariantType::UInt2:
return uiVal != 0;
break;
case VariantType::Int4:
return lVal != 0;
break;
case VariantType::UInt4:
return ulVal != 0;
break;
case VariantType::Int8:
return llVal != 0;
break;
case VariantType::UInt8:
return ullVal != 0;
break;
case VariantType::Real4:
return fltVal != 0.0f;
break;
case VariantType::Real8:
return dblVal != 0.0;
break;
default:
{
VARIANT result = { 0, };
auto hr = VariantChangeType( &result, this, 0, ( VARTYPE )VariantType::Bool );
CheckHRESULT( hr );
return result.boolVal != VARIANT_FALSE;
}
break;
}
}
char AsSByte( ) const
{
char result = 0;
switch ( Type( ) )
{
case VariantType::Bool:
result = boolVal != VARIANT_FALSE ? 1 : 0;
break;
case VariantType::Int1:
result = static_cast<decltype( result )>( cVal );
break;
case VariantType::UInt1:
result = static_cast<decltype( result )>( bVal );
break;
case VariantType::Int2:
result = static_cast<decltype( result )>( iVal );
break;
case VariantType::UInt2:
result = static_cast<decltype( result )>( uiVal );
break;
case VariantType::Int4:
result = static_cast<decltype( result )>( lVal );
break;
case VariantType::UInt4:
result = static_cast<decltype( result )>( ulVal );
break;
case VariantType::Int8:
result = static_cast<decltype( result )>( llVal );
break;
case VariantType::UInt8:
result = static_cast<decltype( result )>( ullVal );
break;
case VariantType::Real4:
result = static_cast<decltype( result )>( fltVal );
break;
case VariantType::Real8:
result = static_cast<decltype( result )>( dblVal );
break;
default:
{
VARIANT result = { 0, };
auto hr = VariantChangeType( &result, this, 0, ( VARTYPE )VariantType::Int1 );
CheckHRESULT( hr );
return result.cVal;
}
break;
}
return result;
}
unsigned char AsByte( ) const
{
unsigned char result = 0;
switch ( Type( ) )
{
case VariantType::Bool:
result = boolVal != VARIANT_FALSE ? 1 : 0;
break;
case VariantType::Int1:
result = static_cast<decltype( result )>( cVal );
break;
case VariantType::UInt1:
result = static_cast<decltype( result )>( bVal );
break;
case VariantType::Int2:
result = static_cast<decltype( result )>( iVal );
break;
case VariantType::UInt2:
result = static_cast<decltype( result )>( uiVal );
break;
case VariantType::Int4:
result = static_cast<decltype( result )>( lVal );
break;
case VariantType::UInt4:
result = static_cast<decltype( result )>( ulVal );
break;
case VariantType::Int8:
result = static_cast<decltype( result )>( llVal );
break;
case VariantType::UInt8:
result = static_cast<decltype( result )>( ullVal );
break;
case VariantType::Real4:
result = static_cast<decltype( result )>( fltVal );
break;
case VariantType::Real8:
result = static_cast<decltype( result )>( dblVal );
break;
default:
{
VARIANT result = { 0, };
auto hr = VariantChangeType( &result, this, 0, ( VARTYPE )VariantType::UInt1 );
CheckHRESULT( hr );
return result.bVal;
}
break;
}
return result;
}
short AsInt16( ) const
{
short result = 0;
switch ( Type( ) )
{
case VariantType::Bool:
result = boolVal != VARIANT_FALSE ? 1 : 0;
break;
case VariantType::Int1:
result = static_cast<decltype( result )>( cVal );
break;
case VariantType::UInt1:
result = static_cast<decltype( result )>( bVal );
break;
case VariantType::Int2:
result = static_cast<decltype( result )>( iVal );
break;
case VariantType::UInt2:
result = static_cast<decltype( result )>( uiVal );
break;
case VariantType::Int4:
result = static_cast<decltype( result )>( lVal );
break;
case VariantType::UInt4:
result = static_cast<decltype( result )>( ulVal );
break;
case VariantType::Int8:
result = static_cast<decltype( result )>( llVal );
break;
case VariantType::UInt8:
result = static_cast<decltype( result )>( ullVal );
break;
case VariantType::Real4:
result = static_cast<decltype( result )>( fltVal );
break;
case VariantType::Real8:
result = static_cast<decltype( result )>( dblVal );
break;
default:
{
VARIANT result = { 0, };
auto hr = VariantChangeType( &result, this, 0, ( VARTYPE )VariantType::Int2 );
CheckHRESULT( hr );
return result.iVal;
}
break;
}
return result;
}
unsigned short AsUInt16( ) const
{
unsigned short result = 0;
switch ( Type( ) )
{
case VariantType::Bool:
result = boolVal != VARIANT_FALSE ? 1 : 0;
break;
case VariantType::Int1:
result = static_cast<decltype( result )>( cVal );
break;
case VariantType::UInt1:
result = static_cast<decltype( result )>( bVal );
break;
case VariantType::Int2:
result = static_cast<decltype( result )>( iVal );
break;
case VariantType::UInt2:
result = static_cast<decltype( result )>( uiVal );
break;
case VariantType::Int4:
result = static_cast<decltype( result )>( lVal );
break;
case VariantType::UInt4:
result = static_cast<decltype( result )>( ulVal );
break;
case VariantType::Int8:
result = static_cast<decltype( result )>( llVal );
break;
case VariantType::UInt8:
result = static_cast<decltype( result )>( ullVal );
break;
case VariantType::Real4:
result = static_cast<decltype( result )>( fltVal );
break;
case VariantType::Real8:
result = static_cast<decltype( result )>( dblVal );
break;
default:
{
VARIANT result = { 0, };
auto hr = VariantChangeType( &result, this, 0, ( VARTYPE )VariantType::UInt2 );
CheckHRESULT( hr );
return result.uiVal;
}
break;
}
return result;
}
int AsInt32( ) const
{
int result = 0;
switch ( Type( ) )
{
case VariantType::Bool:
result = boolVal != VARIANT_FALSE ? 1 : 0;
break;
case VariantType::Int1:
result = static_cast<decltype( result )>( cVal );
break;
case VariantType::UInt1:
result = static_cast<decltype( result )>( bVal );
break;
case VariantType::Int2:
result = static_cast<decltype( result )>( iVal );
break;
case VariantType::UInt2:
result = static_cast<decltype( result )>( uiVal );
break;
case VariantType::Int4:
result = static_cast<decltype( result )>( lVal );
break;
case VariantType::UInt4:
result = static_cast<decltype( result )>( ulVal );
break;
case VariantType::Int8:
result = static_cast<decltype( result )>( llVal );
break;
case VariantType::UInt8:
result = static_cast<decltype( result )>( ullVal );
break;
case VariantType::Real4:
result = static_cast<decltype( result )>( fltVal );
break;
case VariantType::Real8:
result = static_cast<decltype( result )>( dblVal );
break;
default:
{
VARIANT result = { 0, };
auto hr = VariantChangeType( &result, this, 0, ( VARTYPE )VariantType::Int4 );
CheckHRESULT( hr );
return result.lVal;
}
break;
}
return result;
}
unsigned int AsUInt32( ) const
{
unsigned int result = 0;
switch ( Type( ) )
{
case VariantType::Bool:
result = boolVal != VARIANT_FALSE ? 1 : 0;
break;
case VariantType::Int1:
result = static_cast<decltype( result )>( cVal );
break;
case VariantType::UInt1:
result = static_cast<decltype( result )>( bVal );
break;
case VariantType::Int2:
result = static_cast<decltype( result )>( iVal );
break;
case VariantType::UInt2:
result = static_cast<decltype( result )>( uiVal );
break;
case VariantType::Int4:
result = static_cast<decltype( result )>( lVal );
break;
case VariantType::UInt4:
result = static_cast<decltype( result )>( ulVal );
break;
case VariantType::Int8:
result = static_cast<decltype( result )>( llVal );
break;
case VariantType::UInt8:
result = static_cast<decltype( result )>( ullVal );
break;
case VariantType::Real4:
result = static_cast<decltype( result )>( fltVal );
break;
case VariantType::Real8:
result = static_cast<decltype( result )>( dblVal );
break;
default:
{
VARIANT result = { 0, };
auto hr = VariantChangeType( &result, this, 0, ( VARTYPE )VariantType::UInt4 );
CheckHRESULT( hr );
return result.ulVal;
}
break;
}
return result;
}
long long AsInt64( ) const
{
long long result = 0;
switch ( Type( ) )
{
case VariantType::Bool:
result = boolVal != VARIANT_FALSE ? 1 : 0;
break;
case VariantType::Int1:
result = static_cast<decltype( result )>( cVal );
break;
case VariantType::UInt1:
result = static_cast<decltype( result )>( bVal );
break;
case VariantType::Int2:
result = static_cast<decltype( result )>( iVal );
break;
case VariantType::UInt2:
result = static_cast<decltype( result )>( uiVal );
break;
case VariantType::Int4:
result = static_cast<decltype( result )>( lVal );
break;
case VariantType::UInt4:
result = static_cast<decltype( result )>( ulVal );
break;
case VariantType::Int8:
result = static_cast<decltype( result )>( llVal );
break;
case VariantType::UInt8:
result = static_cast<decltype( result )>( ullVal );
break;
case VariantType::Real4:
result = static_cast<decltype( result )>( fltVal );
break;
case VariantType::Real8:
result = static_cast<decltype( result )>( dblVal );
break;
default:
{
VARIANT result = { 0, };
auto hr = VariantChangeType( &result, this, 0, ( VARTYPE )VariantType::Int64 );
CheckHRESULT( hr );
return result.llVal;
}
break;
}
return result;
}
unsigned long long AsUInt64( ) const
{
unsigned long long result = 0;
switch ( Type( ) )
{
case VariantType::Bool:
result = boolVal != VARIANT_FALSE ? 1 : 0;
break;
case VariantType::Int1:
result = static_cast<decltype( result )>( cVal );
break;
case VariantType::UInt1:
result = static_cast<decltype( result )>( bVal );
break;
case VariantType::Int2:
result = static_cast<decltype( result )>( iVal );
break;
case VariantType::UInt2:
result = static_cast<decltype( result )>( uiVal );
break;
case VariantType::Int4:
result = static_cast<decltype( result )>( lVal );
break;
case VariantType::UInt4:
result = static_cast<decltype( result )>( ulVal );
break;
case VariantType::Int8:
result = static_cast<decltype( result )>( llVal );
break;
case VariantType::UInt8:
result = static_cast<decltype( result )>( ullVal );
break;
case VariantType::Real4:
result = static_cast<decltype( result )>( fltVal );
break;
case VariantType::Real8:
result = static_cast<decltype( result )>( dblVal );
break;
default:
{
VARIANT result = { 0, };
auto hr = VariantChangeType( &result, this, 0, ( VARTYPE )VariantType::UInt64 );
CheckHRESULT( hr );
return result.ullVal;
}
break;
}
return result;
}
float AsSingle( ) const
{
float result = 0;
switch ( Type( ) )
{
case VariantType::Bool:
result = boolVal != VARIANT_FALSE ? 1.0f : 0.0f;
break;
case VariantType::Int1:
result = static_cast<decltype( result )>( cVal );
break;
case VariantType::UInt1:
result = static_cast<decltype( result )>( bVal );
break;
case VariantType::Int2:
result = static_cast<decltype( result )>( iVal );
break;
case VariantType::UInt2:
result = static_cast<decltype( result )>( uiVal );
break;
case VariantType::Int4:
result = static_cast<decltype( result )>( lVal );
break;
case VariantType::UInt4:
result = static_cast<decltype( result )>( ulVal );
break;
case VariantType::Int8:
result = static_cast<decltype( result )>( llVal );
break;
case VariantType::UInt8:
result = static_cast<decltype( result )>( ullVal );
break;
case VariantType::Real4:
result = static_cast<decltype( result )>( fltVal );
break;
case VariantType::Real8:
result = static_cast<decltype( result )>( dblVal );
break;
default:
{
VARIANT result = { 0, };
auto hr = VariantChangeType( &result, this, 0, ( VARTYPE )VariantType::Real4 );
CheckHRESULT( hr );
return result.fltVal;
}
break;
}
return result;
}
double AsDouble( ) const
{
double result = 0;
switch ( Type( ) )
{
case VariantType::Bool:
result = boolVal != VARIANT_FALSE ? 1 : 0;
break;
case VariantType::Int1:
result = static_cast<decltype( result )>( cVal );
break;
case VariantType::UInt1:
result = static_cast<decltype( result )>( bVal );
break;
case VariantType::Int2:
result = static_cast<decltype( result )>( iVal );
break;
case VariantType::UInt2:
result = static_cast<decltype( result )>( uiVal );
break;
case VariantType::Int4:
result = static_cast<decltype( result )>( lVal );
break;
case VariantType::UInt4:
result = static_cast<decltype( result )>( ulVal );
break;
case VariantType::Int8:
result = static_cast<decltype( result )>( llVal );
break;
case VariantType::UInt8:
result = static_cast<decltype( result )>( ullVal );
break;
case VariantType::Real4:
result = static_cast<decltype( result )>( fltVal );
break;
case VariantType::Real8:
result = static_cast<decltype( result )>( dblVal );
break;
default:
{
VARIANT result = { 0, };
auto hr = VariantChangeType( &result, this, 0, ( VARTYPE )VariantType::Real8 );
CheckHRESULT( hr );
return result.dblVal;
}
break;
}
return result;
}
String AsString( ) const
{
if ( Type( ) == VariantType::BStr )
{
if ( bstrVal )
{
return String::From( bstrVal );
}
else
{
return String( );
}
}
else
{
Variant result;
auto hr = VariantChangeType( &result, this, 0, ( VARTYPE )VariantType::BStr );
CheckHRESULT( hr );
if ( result.bstrVal )
{
return String::From( result.bstrVal );
}
else
{
return String( );
}
}
}
WideString AsWideString( ) const
{
if ( Type( ) == VariantType::BStr )
{
if ( bstrVal )
{
return WideString::From( bstrVal );
}
else
{
return WideString( );
}
}
else
{
Variant result;
auto hr = VariantChangeType( &result, this, 0, ( VARTYPE )VariantType::BStr );
CheckHRESULT( hr );
if ( result.bstrVal )
{
return WideString::From( result.bstrVal );
}
else
{
return WideString( );
}
}
}
DateTime AsDateTime( ) const
{
if ( Type( ) == VariantType::DateTime )
{
return DateTime::FromOADate( date );
}
else
{
Variant result;
auto hr = VariantChangeType( &result, this, 0, ( VARTYPE )VariantType::DateTime );
CheckHRESULT( hr );
return DateTime::FromOADate( result.date );
}
}
TimeSpan AsTimeSpan( ) const
{
auto type = Type( );
if ( type == VariantType::Real8 )
{
return TimeSpan::FromDays( dblVal );
}
else if ( type == VariantType::Real4 )
{
return TimeSpan::FromDays( fltVal );
}
else
{
Variant result;
auto hr = VariantChangeType( &result, this, 0, ( VARTYPE )VariantType::Real8 );
CheckHRESULT( hr );
return TimeSpan::FromDays( result.dblVal );
}
}
Guid AsGuid( ) const
{
return Guid( AsWideString( ) );
}
Variant Abs( ) const
{
Variant result;
auto hr = VarAbs( ( LPVARIANT )this, &result );
if ( FAILED( hr ) )
{
CheckHRESULT( hr );
}
return result;
}
Variant Add( const Variant& other ) const
{
Variant result;
auto hr = VarAdd( ( LPVARIANT )this, ( LPVARIANT )&other, &result );
if ( FAILED( hr ) )
{
CheckHRESULT( hr );
}
return result;
}
friend Variant operator + ( const Variant& left, const Variant& right )
{
return left.Add( right );
}
Variant And( const Variant& other ) const
{
Variant result;
auto hr = VarAnd( ( LPVARIANT )this, ( LPVARIANT )&other, &result );
if ( FAILED( hr ) )
{
CheckHRESULT( hr );
}
return result;
}
friend Variant operator & ( const Variant& left, const Variant& right )
{
return left.And( right );
}
Variant Concatenate( const Variant& other ) const
{
Variant result;
auto hr = VarCat( ( LPVARIANT )this, ( LPVARIANT )&other, &result );
if ( FAILED( hr ) )
{
CheckHRESULT( hr );
}
return result;
}
Variant Div( const Variant& other ) const
{
Variant result;
auto hr = VarDiv( ( LPVARIANT )this, ( LPVARIANT )&other, &result );
if ( FAILED( hr ) )
{
CheckHRESULT( hr );
}
return result;
}
friend Variant operator / ( const Variant& left, const Variant& right )
{
return left.Div( right );
}
Variant IDiv( const Variant& other ) const
{
Variant result;
auto hr = VarIdiv( ( LPVARIANT )this, ( LPVARIANT )&other, &result );
if ( FAILED( hr ) )
{
CheckHRESULT( hr );
}
return result;
}
Variant Trunc( ) const
{
Variant result;
auto hr = VarFix( ( LPVARIANT )this, &result );
if ( FAILED( hr ) )
{
CheckHRESULT( hr );
}
return result;
}
Variant Mod( const Variant& other ) const
{
Variant result;
auto hr = VarMod( ( LPVARIANT )this, ( LPVARIANT )&other, &result );
if ( FAILED( hr ) )
{
CheckHRESULT( hr );
}
return result;
}
friend Variant operator % ( const Variant& left, const Variant& right )
{
return left.Mod( right );
}
Variant Mul( const Variant& other ) const
{
Variant result;
auto hr = VarMul( ( LPVARIANT )this, ( LPVARIANT )&other, &result );
if ( FAILED( hr ) )
{
CheckHRESULT( hr );
}
return result;
}
friend Variant operator * ( const Variant& left, const Variant& right )
{
return left.Mod( right );
}
Variant Neg( ) const
{
Variant result;
auto hr = VarNeg( ( LPVARIANT )this, &result );
if ( FAILED( hr ) )
{
CheckHRESULT( hr );
}
return result;
}
Variant Not( ) const
{
Variant result;
auto hr = VarNot( ( LPVARIANT )this, &result );
if ( FAILED( hr ) )
{
CheckHRESULT( hr );
}
return result;
}
Variant operator ! ( ) const
{
return Not( );
}
Variant Or( const Variant& other ) const
{
Variant result;
auto hr = VarOr( ( LPVARIANT )this, ( LPVARIANT )&other, &result );
if ( FAILED( hr ) )
{
CheckHRESULT( hr );
}
return result;
}
friend Variant operator | ( const Variant& left, const Variant& right )
{
return left.Or( right );
}
Variant Sub( const Variant& other ) const
{
Variant result;
auto hr = VarSub( ( LPVARIANT )this, ( LPVARIANT )&other, &result );
if ( FAILED( hr ) )
{
CheckHRESULT( hr );
}
return result;
}
friend Variant operator - ( const Variant& left, const Variant& right )
{
return left.Sub( right );
}
Variant Pow( const Variant& other ) const
{
Variant result;
auto hr = VarPow( ( LPVARIANT )this, ( LPVARIANT )&other, &result );
if ( FAILED( hr ) )
{
CheckHRESULT( hr );
}
return result;
}
};
// ----------------------------------------------------------------------
// PropertyVariant
// ----------------------------------------------------------------------
class PropertyVariant : public PROPVARIANT
{
void SetVariantType( VariantType variantType )
{
vt = USHORT( variantType );
}
public:
// Temporary solution, will probably not work well for those types
// that are specific to PROPVARIANT.
// Relies on the fact that VARIANT and PROPVARIANT have the same
// binary layout.
static int Compare( const PROPVARIANT& first, const PROPVARIANT& second )
{
if ( first.vt == USHORT( VariantType::Empty ) )
{
if ( second.vt == USHORT( VariantType::Empty ) )
{
return 0;
}
return -1;
}
else if ( second.vt == USHORT( VariantType::Empty ) )
{
return 1;
}
else if ( first.vt == USHORT( VariantType::Null ) )
{
if ( second.vt == USHORT( VariantType::Null ) )
{
return 0;
}
return -1;
}
else if ( second.vt == USHORT( VariantType::Null ) )
{
return 1;
}
auto lcid = GetUserDefaultLCID( );
auto result = VarCmp( ( VARIANT* )&first, ( VARIANT* )&second, lcid );
if ( FAILED( result ) )
{
CheckHRESULT( result );
}
return result - 1;
}
VariantType Type( ) const
{
return VariantType( vt );
}
VariantType ElementType( ) const
{
return VariantType( vt & VT_TYPEMASK );
}
bool IsEmpty( ) const
{
return Type( ) == VariantType::Empty;
}
bool IsNull( ) const
{
return Type( ) == VariantType::Null;
}
bool IsReference( ) const
{
return ( Type( ) & VariantType::Byref ) != VariantType::Empty;
}
bool IsArray( ) const
{
return ( Type( ) & VariantType::Array ) != VariantType::Empty;
}
PropertyVariant( )
{
SetVariantType( VariantType::Empty );
}
PropertyVariant( INT64 theValue )
{
SetVariantType( VariantType::Int64 );
hVal.QuadPart = theValue;
}
PropertyVariant( UINT64 theValue )
{
SetVariantType( VariantType::UInt64 );
uhVal.QuadPart = theValue;
}
PropertyVariant( LONG theValue )
{
SetVariantType( VariantType::Long );
lVal = theValue;
}
PropertyVariant( LONG theValue, VariantType variantType )
{
if ( variantType == VariantType::Long || variantType == VariantType::Error )
{
SetVariantType( variantType );
lVal = theValue;
}
else
{
SetVariantType( VariantType::Error );
scode = E_INVALIDARG;
CheckHRESULT( scode );
}
}
PropertyVariant( BYTE theValue )
{
SetVariantType( VariantType::Byte );
bVal = theValue;
}
PropertyVariant( SHORT theValue )
{
SetVariantType( VariantType::Short );
iVal = theValue;
}
PropertyVariant( FLOAT theValue )
{
SetVariantType( VariantType::Float );
fltVal = theValue;
}
PropertyVariant( DOUBLE theValue )
{
SetVariantType( VariantType::Double );
dblVal = theValue;
}
PropertyVariant( DOUBLE theValue, VariantType variantType )
{
if ( variantType == VariantType::Double || variantType == VariantType::DateTime )
{
SetVariantType( variantType );
dblVal = theValue;
}
else
{
SetVariantType( VariantType::Error );
scode = E_INVALIDARG;
CheckHRESULT( scode );
}
}
PropertyVariant( bool theValue )
{
SetVariantType( VariantType::Bool );
boolVal = theValue ? VARIANT_TRUE : VARIANT_FALSE;
}
PropertyVariant( const CY& theValue )
{
SetVariantType( VariantType::Currency );
cyVal = theValue;
}
PropertyVariant( const DateTime& theValue )
{
SetVariantType( VariantType::DateTime );
date = theValue.ToOADate( );
}
PropertyVariant( const TimeSpan& theValue )
{
SetVariantType( VariantType::DateTime );
date = theValue.TotalDays( );
}
PropertyVariant( const FILETIME& theValue )
{
SetVariantType( VariantType::FileTime );
filetime = theValue;
}
PropertyVariant( const SysString& theValue )
{
SetVariantType( VariantType::BStr );
bstrVal = theValue.Copy( );
}
PropertyVariant( IUnknown* pInterface )
{
SetVariantType( VariantType::Unknown );
punkVal = pInterface;
if ( punkVal )
{
punkVal->AddRef( );
}
}
PropertyVariant( IDispatch* pInterface )
{
SetVariantType( VariantType::Dispatch );
pdispVal = pInterface;
if ( pdispVal )
{
pdispVal->AddRef( );
}
}
PropertyVariant( SAFEARRAY* safeArray )
{
SetVariantType( VariantType::Array );
if ( safeArray )
{
auto vType = SafeArray::GetElementVariantType( safeArray );
SetVariantType( VariantType::Array | vType );
auto hr = SafeArrayCopy( safeArray, &parray );
CheckHRESULT( hr );
}
else
{
parray = nullptr;
}
}
PropertyVariant( CHAR theValue )
{
SetVariantType( VariantType::SByte );
cVal = theValue;
}
PropertyVariant( USHORT theValue )
{
SetVariantType( VariantType::UShort );
uiVal = theValue;
}
PropertyVariant( ULONG theValue )
{
SetVariantType( VariantType::ULong );
ulVal = theValue;
}
PropertyVariant( const PropertyVariant& other )
{
PropVariantInit( this );
auto hr = PropVariantCopy( this, &other );
CheckHRESULT( hr );
}
PropertyVariant( PropertyVariant&& other )
{
memcpy( &vt, &other.vt, sizeof( VARIANT ) );
memset( &other.vt, 0, sizeof( VARIANT ) );
}
PropertyVariant& Clear( )
{
switch ( vt )
{
case VT_EMPTY:
case VT_NULL:
case VT_I1:
case VT_I2:
case VT_I4:
case VT_I8:
case VT_UI1:
case VT_UI2:
case VT_UI4:
case VT_UI8:
case VT_R4:
case VT_R8:
case VT_CY:
case VT_DATE:
vt = VT_EMPTY;
break;
default:
auto hr = PropVariantClear( this );
CheckHRESULT( hr );
break;
}
return *this;
}
~PropertyVariant( )
{
if ( vt != VT_EMPTY )
{
Clear( );
}
}
PropertyVariant& operator = ( const PropertyVariant& other )
{
if ( &vt != &other.vt )
{
if ( vt != VT_EMPTY )
{
Clear( );
}
auto hr = PropVariantCopy( this, &other );
CheckHRESULT( hr );
}
return *this;
}
PropertyVariant& operator = ( PropertyVariant&& other )
{
if ( this != &other )
{
if ( vt != VT_EMPTY )
{
Clear( );
}
memcpy( &vt, &other.vt, sizeof( VARIANT ) );
memset( &other.vt, 0, sizeof( VARIANT ) );
}
}
PropertyVariant& Assign( INT64 theValue )
{
Clear( );
SetVariantType( VariantType::Int64 );
hVal.QuadPart = theValue;
return *this;
}
PropertyVariant& Assign( UINT64 theValue )
{
Clear( );
SetVariantType( VariantType::UInt64 );
uhVal.QuadPart = theValue;
return *this;
}
PropertyVariant& Assign( LONG theValue )
{
Clear( );
SetVariantType( VariantType::Long );
lVal = theValue;
return *this;
}
PropertyVariant& Assign( LONG theValue, VariantType variantType )
{
Clear( );
if ( variantType == VariantType::Long || variantType == VariantType::Error )
{
SetVariantType( variantType );
lVal = theValue;
}
else
{
SetVariantType( VariantType::Error );
scode = E_INVALIDARG;
CheckHRESULT( scode );
}
return *this;
}
PropertyVariant& Assign( BYTE theValue )
{
Clear( );
SetVariantType( VariantType::Byte );
bVal = theValue;
return *this;
}
PropertyVariant& Assign( SHORT theValue )
{
Clear( );
SetVariantType( VariantType::Short );
iVal = theValue;
return *this;
}
PropertyVariant& Assign( FLOAT theValue )
{
Clear( );
SetVariantType( VariantType::Float );
fltVal = theValue;
return *this;
}
PropertyVariant& Assign( DOUBLE theValue )
{
Clear( );
SetVariantType( VariantType::Double );
dblVal = theValue;
return *this;
}
PropertyVariant& Assign( DOUBLE theValue, VariantType variantType )
{
Clear( );
if ( variantType == VariantType::Double || variantType == VariantType::DateTime )
{
SetVariantType( variantType );
dblVal = theValue;
}
else
{
SetVariantType( VariantType::Error );
scode = E_INVALIDARG;
CheckHRESULT( scode );
}
return *this;
}
PropertyVariant& Assign( bool theValue )
{
Clear( );
SetVariantType( VariantType::Bool );
boolVal = theValue ? VARIANT_TRUE : VARIANT_FALSE;
return *this;
}
PropertyVariant& Assign( const CY& theValue )
{
Clear( );
SetVariantType( VariantType::Currency );
cyVal = theValue;
return *this;
}
PropertyVariant& Assign( const DateTime& theValue )
{
Clear( );
SetVariantType( VariantType::DateTime );
date = theValue.ToOADate( );
return *this;
}
PropertyVariant& Assign( const TimeSpan& theValue )
{
Clear( );
SetVariantType( VariantType::Double );
date = theValue.TotalDays( );
return *this;
}
PropertyVariant& Assign( const SysString& theValue )
{
Clear( );
SetVariantType( VariantType::BStr );
bstrVal = theValue.Copy( );
return *this;
}
PropertyVariant& Assign( IUnknown* pInterface )
{
Clear( );
SetVariantType( VariantType::Unknown );
punkVal = pInterface;
if ( punkVal )
{
punkVal->AddRef( );
}
return *this;
}
PropertyVariant& Assign( IDispatch* pInterface )
{
Clear( );
SetVariantType( VariantType::Dispatch );
pdispVal = pInterface;
if ( pdispVal )
{
pdispVal->AddRef( );
}
return *this;
}
PropertyVariant& Assign( SAFEARRAY* safeArray )
{
Clear( );
SetVariantType( VariantType::Array );
if ( safeArray )
{
auto vType = SafeArray::GetElementVariantType( safeArray );
SetVariantType( VariantType::Array | vType );
auto hr = SafeArrayCopy( safeArray, &parray );
CheckHRESULT( hr );
}
else
{
parray = nullptr;
}
return *this;
}
PropertyVariant& Assign( CHAR theValue )
{
Clear( );
SetVariantType( VariantType::SByte );
cVal = theValue;
return *this;
}
PropertyVariant& Assign( USHORT theValue )
{
Clear( );
SetVariantType( VariantType::UShort );
uiVal = theValue;
return *this;
}
PropertyVariant& Assign( ULONG theValue )
{
Clear( );
SetVariantType( VariantType::ULong );
ulVal = theValue;
return *this;
}
};
}
}
#endif //__HWINVARIANT_H__