Home | History | Annotate | Download | only in Windows
      1 // Windows/PropVariant.cpp
      2 
      3 #include "StdAfx.h"
      4 
      5 #include "PropVariant.h"
      6 
      7 #include "../Common/Defs.h"
      8 
      9 namespace NWindows {
     10 namespace NCOM {
     11 
     12 CPropVariant::CPropVariant(const PROPVARIANT &varSrc)
     13 {
     14   vt = VT_EMPTY;
     15   InternalCopy(&varSrc);
     16 }
     17 
     18 CPropVariant::CPropVariant(const CPropVariant &varSrc)
     19 {
     20   vt = VT_EMPTY;
     21   InternalCopy(&varSrc);
     22 }
     23 
     24 CPropVariant::CPropVariant(BSTR bstrSrc)
     25 {
     26   vt = VT_EMPTY;
     27   *this = bstrSrc;
     28 }
     29 
     30 CPropVariant::CPropVariant(LPCOLESTR lpszSrc)
     31 {
     32   vt = VT_EMPTY;
     33   *this = lpszSrc;
     34 }
     35 
     36 CPropVariant& CPropVariant::operator=(const CPropVariant &varSrc)
     37 {
     38   InternalCopy(&varSrc);
     39   return *this;
     40 }
     41 CPropVariant& CPropVariant::operator=(const PROPVARIANT &varSrc)
     42 {
     43   InternalCopy(&varSrc);
     44   return *this;
     45 }
     46 
     47 CPropVariant& CPropVariant::operator=(BSTR bstrSrc)
     48 {
     49   *this = (LPCOLESTR)bstrSrc;
     50   return *this;
     51 }
     52 
     53 static const char *kMemException = "out of memory";
     54 
     55 CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc)
     56 {
     57   InternalClear();
     58   vt = VT_BSTR;
     59   wReserved1 = 0;
     60   bstrVal = ::SysAllocString(lpszSrc);
     61   if (bstrVal == NULL && lpszSrc != NULL)
     62   {
     63     throw kMemException;
     64     // vt = VT_ERROR;
     65     // scode = E_OUTOFMEMORY;
     66   }
     67   return *this;
     68 }
     69 
     70 
     71 CPropVariant& CPropVariant::operator=(const char *s)
     72 {
     73   InternalClear();
     74   vt = VT_BSTR;
     75   wReserved1 = 0;
     76   UINT len = (UINT)strlen(s);
     77   bstrVal = ::SysAllocStringByteLen(0, (UINT)len * sizeof(OLECHAR));
     78   if (bstrVal == NULL)
     79   {
     80     throw kMemException;
     81     // vt = VT_ERROR;
     82     // scode = E_OUTOFMEMORY;
     83   }
     84   else
     85   {
     86     for (UINT i = 0; i <= len; i++)
     87       bstrVal[i] = s[i];
     88   }
     89   return *this;
     90 }
     91 
     92 CPropVariant& CPropVariant::operator=(bool bSrc)
     93 {
     94   if (vt != VT_BOOL)
     95   {
     96     InternalClear();
     97     vt = VT_BOOL;
     98   }
     99   boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE;
    100   return *this;
    101 }
    102 
    103 #define SET_PROP_FUNC(type, id, dest) \
    104   CPropVariant& CPropVariant::operator=(type value) \
    105   { if (vt != id) { InternalClear(); vt = id; } \
    106     dest = value; return *this; }
    107 
    108 SET_PROP_FUNC(Byte, VT_UI1, bVal)
    109 SET_PROP_FUNC(Int16, VT_I2, iVal)
    110 SET_PROP_FUNC(Int32, VT_I4, lVal)
    111 SET_PROP_FUNC(UInt32, VT_UI4, ulVal)
    112 SET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart)
    113 SET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime)
    114 
    115 static HRESULT MyPropVariantClear(PROPVARIANT *prop)
    116 {
    117   switch(prop->vt)
    118   {
    119     case VT_UI1:
    120     case VT_I1:
    121     case VT_I2:
    122     case VT_UI2:
    123     case VT_BOOL:
    124     case VT_I4:
    125     case VT_UI4:
    126     case VT_R4:
    127     case VT_INT:
    128     case VT_UINT:
    129     case VT_ERROR:
    130     case VT_FILETIME:
    131     case VT_UI8:
    132     case VT_R8:
    133     case VT_CY:
    134     case VT_DATE:
    135       prop->vt = VT_EMPTY;
    136       prop->wReserved1 = 0;
    137       return S_OK;
    138   }
    139   return ::VariantClear((VARIANTARG *)prop);
    140 }
    141 
    142 HRESULT CPropVariant::Clear()
    143 {
    144   return MyPropVariantClear(this);
    145 }
    146 
    147 HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc)
    148 {
    149   ::VariantClear((tagVARIANT *)this);
    150   switch(pSrc->vt)
    151   {
    152     case VT_UI1:
    153     case VT_I1:
    154     case VT_I2:
    155     case VT_UI2:
    156     case VT_BOOL:
    157     case VT_I4:
    158     case VT_UI4:
    159     case VT_R4:
    160     case VT_INT:
    161     case VT_UINT:
    162     case VT_ERROR:
    163     case VT_FILETIME:
    164     case VT_UI8:
    165     case VT_R8:
    166     case VT_CY:
    167     case VT_DATE:
    168       memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT));
    169       return S_OK;
    170   }
    171   return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)const_cast<PROPVARIANT *>(pSrc));
    172 }
    173 
    174 
    175 HRESULT CPropVariant::Attach(PROPVARIANT *pSrc)
    176 {
    177   HRESULT hr = Clear();
    178   if (FAILED(hr))
    179     return hr;
    180   memcpy(this, pSrc, sizeof(PROPVARIANT));
    181   pSrc->vt = VT_EMPTY;
    182   return S_OK;
    183 }
    184 
    185 HRESULT CPropVariant::Detach(PROPVARIANT *pDest)
    186 {
    187   HRESULT hr = MyPropVariantClear(pDest);
    188   if (FAILED(hr))
    189     return hr;
    190   memcpy(pDest, this, sizeof(PROPVARIANT));
    191   vt = VT_EMPTY;
    192   return S_OK;
    193 }
    194 
    195 HRESULT CPropVariant::InternalClear()
    196 {
    197   HRESULT hr = Clear();
    198   if (FAILED(hr))
    199   {
    200     vt = VT_ERROR;
    201     scode = hr;
    202   }
    203   return hr;
    204 }
    205 
    206 void CPropVariant::InternalCopy(const PROPVARIANT *pSrc)
    207 {
    208   HRESULT hr = Copy(pSrc);
    209   if (FAILED(hr))
    210   {
    211     if (hr == E_OUTOFMEMORY)
    212       throw kMemException;
    213     vt = VT_ERROR;
    214     scode = hr;
    215   }
    216 }
    217 
    218 int CPropVariant::Compare(const CPropVariant &a)
    219 {
    220   if (vt != a.vt)
    221     return MyCompare(vt, a.vt);
    222   switch (vt)
    223   {
    224     case VT_EMPTY: return 0;
    225     // case VT_I1: return MyCompare(cVal, a.cVal);
    226     case VT_UI1: return MyCompare(bVal, a.bVal);
    227     case VT_I2: return MyCompare(iVal, a.iVal);
    228     case VT_UI2: return MyCompare(uiVal, a.uiVal);
    229     case VT_I4: return MyCompare(lVal, a.lVal);
    230     case VT_UI4: return MyCompare(ulVal, a.ulVal);
    231     // case VT_UINT: return MyCompare(uintVal, a.uintVal);
    232     case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart);
    233     case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart);
    234     case VT_BOOL: return -MyCompare(boolVal, a.boolVal);
    235     case VT_FILETIME: return ::CompareFileTime(&filetime, &a.filetime);
    236     case VT_BSTR:
    237       return 0; // Not implemented
    238       // return MyCompare(aPropVarint.cVal);
    239     default: return 0;
    240   }
    241 }
    242 
    243 }}
    244