tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

PropVariant.cpp (7603B)


      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 BSTR AllocBstrFromAscii(const char *s) throw()
     13 {
     14  if (!s)
     15    return NULL;
     16  UINT len = (UINT)strlen(s);
     17  BSTR p = ::SysAllocStringLen(NULL, len);
     18  if (p)
     19  {
     20    for (UINT i = 0; i <= len; i++)
     21      p[i] = (Byte)s[i];
     22  }
     23  return p;
     24 }
     25 
     26 HRESULT PropVarEm_Alloc_Bstr(PROPVARIANT *p, unsigned numChars) throw()
     27 {
     28  p->bstrVal = ::SysAllocStringLen(NULL, numChars);
     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  return S_OK;
     37 }
     38 
     39 HRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw()
     40 {
     41  p->bstrVal = AllocBstrFromAscii(s);
     42  if (p->bstrVal)
     43  {
     44    p->vt = VT_BSTR;
     45    return S_OK;
     46  }
     47  p->vt = VT_ERROR;
     48  p->scode = E_OUTOFMEMORY;
     49  return E_OUTOFMEMORY;
     50 }
     51 
     52 CPropVariant::CPropVariant(const PROPVARIANT &varSrc)
     53 {
     54  vt = VT_EMPTY;
     55  InternalCopy(&varSrc);
     56 }
     57 
     58 CPropVariant::CPropVariant(const CPropVariant &varSrc)
     59 {
     60  vt = VT_EMPTY;
     61  InternalCopy(&varSrc);
     62 }
     63 
     64 CPropVariant::CPropVariant(BSTR bstrSrc)
     65 {
     66  vt = VT_EMPTY;
     67  *this = bstrSrc;
     68 }
     69 
     70 CPropVariant::CPropVariant(LPCOLESTR lpszSrc)
     71 {
     72  vt = VT_EMPTY;
     73  *this = lpszSrc;
     74 }
     75 
     76 CPropVariant& CPropVariant::operator=(const CPropVariant &varSrc)
     77 {
     78  InternalCopy(&varSrc);
     79  return *this;
     80 }
     81 
     82 CPropVariant& CPropVariant::operator=(const PROPVARIANT &varSrc)
     83 {
     84  InternalCopy(&varSrc);
     85  return *this;
     86 }
     87 
     88 CPropVariant& CPropVariant::operator=(BSTR bstrSrc)
     89 {
     90  *this = (LPCOLESTR)bstrSrc;
     91  return *this;
     92 }
     93 
     94 static const char * const kMemException = "out of memory";
     95 
     96 CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc)
     97 {
     98  InternalClear();
     99  vt = VT_BSTR;
    100  wReserved1 = 0;
    101  bstrVal = ::SysAllocString(lpszSrc);
    102  if (!bstrVal && lpszSrc)
    103  {
    104    throw kMemException;
    105    // vt = VT_ERROR;
    106    // scode = E_OUTOFMEMORY;
    107  }
    108  return *this;
    109 }
    110 
    111 CPropVariant& CPropVariant::operator=(const UString &s)
    112 {
    113  InternalClear();
    114  vt = VT_BSTR;
    115  wReserved1 = 0;
    116  bstrVal = ::SysAllocStringLen(s, s.Len());
    117  if (!bstrVal)
    118    throw kMemException;
    119  return *this;
    120 }
    121 
    122 CPropVariant& CPropVariant::operator=(const UString2 &s)
    123 {
    124  /*
    125  if (s.IsEmpty())
    126    *this = L"";
    127  else
    128  */
    129  {
    130    InternalClear();
    131    vt = VT_BSTR;
    132    wReserved1 = 0;
    133    bstrVal = ::SysAllocStringLen(s.GetRawPtr(), s.Len());
    134    if (!bstrVal)
    135      throw kMemException;
    136    /* SysAllocStringLen probably appends a null-terminating character for NULL string.
    137       But it doesn't specified in MSDN.
    138       But we suppose that it works
    139 
    140    if (!s.GetRawPtr())
    141    {
    142      *bstrVal = 0;
    143    }
    144    */
    145 
    146    /* MSDN: Windows CE: SysAllocStringLen() : Passing invalid (and under some circumstances NULL)
    147                         pointers to this function causes  an unexpected termination of the application.
    148       Is it safe? Maybe we must chamnge the code for that case ? */
    149  }
    150  return *this;
    151 }
    152 
    153 CPropVariant& CPropVariant::operator=(const char *s)
    154 {
    155  InternalClear();
    156  vt = VT_BSTR;
    157  wReserved1 = 0;
    158  bstrVal = AllocBstrFromAscii(s);
    159  if (!bstrVal)
    160  {
    161    throw kMemException;
    162    // vt = VT_ERROR;
    163    // scode = E_OUTOFMEMORY;
    164  }
    165  return *this;
    166 }
    167 
    168 CPropVariant& CPropVariant::operator=(bool bSrc) throw()
    169 {
    170  if (vt != VT_BOOL)
    171  {
    172    InternalClear();
    173    vt = VT_BOOL;
    174  }
    175  boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE;
    176  return *this;
    177 }
    178 
    179 BSTR CPropVariant::AllocBstr(unsigned numChars)
    180 {
    181  if (vt != VT_EMPTY)
    182    InternalClear();
    183  vt = VT_BSTR;
    184  wReserved1 = 0;
    185  bstrVal = ::SysAllocStringLen(NULL, numChars);
    186  if (!bstrVal)
    187  {
    188    throw kMemException;
    189    // vt = VT_ERROR;
    190    // scode = E_OUTOFMEMORY;
    191  }
    192  return bstrVal;
    193 }
    194 
    195 #define SET_PROP_FUNC(type, id, dest) \
    196  CPropVariant& CPropVariant::operator=(type value) throw() \
    197  { if (vt != id) { InternalClear(); vt = id; } \
    198    dest = value; return *this; }
    199 
    200 SET_PROP_FUNC(Byte, VT_UI1, bVal)
    201 // SET_PROP_FUNC(Int16, VT_I2, iVal)
    202 SET_PROP_FUNC(Int32, VT_I4, lVal)
    203 SET_PROP_FUNC(UInt32, VT_UI4, ulVal)
    204 SET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart)
    205 SET_PROP_FUNC(Int64, VT_I8, hVal.QuadPart)
    206 SET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime)
    207 
    208 HRESULT PropVariant_Clear(PROPVARIANT *prop) throw()
    209 {
    210  switch (prop->vt)
    211  {
    212    case VT_EMPTY:
    213    case VT_UI1:
    214    case VT_I1:
    215    case VT_I2:
    216    case VT_UI2:
    217    case VT_BOOL:
    218    case VT_I4:
    219    case VT_UI4:
    220    case VT_R4:
    221    case VT_INT:
    222    case VT_UINT:
    223    case VT_ERROR:
    224    case VT_FILETIME:
    225    case VT_UI8:
    226    case VT_R8:
    227    case VT_CY:
    228    case VT_DATE:
    229      prop->vt = VT_EMPTY;
    230      prop->wReserved1 = 0;
    231      prop->wReserved2 = 0;
    232      prop->wReserved3 = 0;
    233      prop->uhVal.QuadPart = 0;
    234      return S_OK;
    235  }
    236  return ::VariantClear((VARIANTARG *)prop);
    237  // return ::PropVariantClear(prop);
    238  // PropVariantClear can clear VT_BLOB.
    239 }
    240 
    241 HRESULT CPropVariant::Clear() throw()
    242 {
    243  if (vt == VT_EMPTY)
    244    return S_OK;
    245  return PropVariant_Clear(this);
    246 }
    247 
    248 HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) throw()
    249 {
    250  ::VariantClear((tagVARIANT *)this);
    251  switch (pSrc->vt)
    252  {
    253    case VT_UI1:
    254    case VT_I1:
    255    case VT_I2:
    256    case VT_UI2:
    257    case VT_BOOL:
    258    case VT_I4:
    259    case VT_UI4:
    260    case VT_R4:
    261    case VT_INT:
    262    case VT_UINT:
    263    case VT_ERROR:
    264    case VT_FILETIME:
    265    case VT_UI8:
    266    case VT_R8:
    267    case VT_CY:
    268    case VT_DATE:
    269      memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT));
    270      return S_OK;
    271  }
    272  return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)const_cast<PROPVARIANT *>(pSrc));
    273 }
    274 
    275 
    276 HRESULT CPropVariant::Attach(PROPVARIANT *pSrc) throw()
    277 {
    278  HRESULT hr = Clear();
    279  if (FAILED(hr))
    280    return hr;
    281  memcpy(this, pSrc, sizeof(PROPVARIANT));
    282  pSrc->vt = VT_EMPTY;
    283  return S_OK;
    284 }
    285 
    286 HRESULT CPropVariant::Detach(PROPVARIANT *pDest) throw()
    287 {
    288  if (pDest->vt != VT_EMPTY)
    289  {
    290    HRESULT hr = PropVariant_Clear(pDest);
    291    if (FAILED(hr))
    292      return hr;
    293  }
    294  memcpy(pDest, this, sizeof(PROPVARIANT));
    295  vt = VT_EMPTY;
    296  return S_OK;
    297 }
    298 
    299 HRESULT CPropVariant::InternalClear() throw()
    300 {
    301  if (vt == VT_EMPTY)
    302    return S_OK;
    303  HRESULT hr = Clear();
    304  if (FAILED(hr))
    305  {
    306    vt = VT_ERROR;
    307    scode = hr;
    308  }
    309  return hr;
    310 }
    311 
    312 void CPropVariant::InternalCopy(const PROPVARIANT *pSrc)
    313 {
    314  HRESULT hr = Copy(pSrc);
    315  if (FAILED(hr))
    316  {
    317    if (hr == E_OUTOFMEMORY)
    318      throw kMemException;
    319    vt = VT_ERROR;
    320    scode = hr;
    321  }
    322 }
    323 
    324 int CPropVariant::Compare(const CPropVariant &a) throw()
    325 {
    326  if (vt != a.vt)
    327    return MyCompare(vt, a.vt);
    328  switch (vt)
    329  {
    330    case VT_EMPTY: return 0;
    331    // case VT_I1: return MyCompare(cVal, a.cVal);
    332    case VT_UI1: return MyCompare(bVal, a.bVal);
    333    case VT_I2: return MyCompare(iVal, a.iVal);
    334    case VT_UI2: return MyCompare(uiVal, a.uiVal);
    335    case VT_I4: return MyCompare(lVal, a.lVal);
    336    case VT_UI4: return MyCompare(ulVal, a.ulVal);
    337    // case VT_UINT: return MyCompare(uintVal, a.uintVal);
    338    case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart);
    339    case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart);
    340    case VT_BOOL: return -MyCompare(boolVal, a.boolVal);
    341    case VT_FILETIME: return ::CompareFileTime(&filetime, &a.filetime);
    342    case VT_BSTR: return 0; // Not implemented
    343    default: return 0;
    344  }
    345 }
    346 
    347 }}