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