master
   1/**
   2 * This file has no copyright assigned and is placed in the Public Domain.
   3 * This file is part of the mingw-w64 runtime package.
   4 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
   5 */
   6#ifndef _INC_COMUTIL
   7#define _INC_COMUTIL
   8
   9#include <ole2.h>
  10#include <stdio.h>
  11
  12#ifndef _COM_ASSERT
  13#define _COM_ASSERT(x) ((void)0)
  14#endif
  15
  16#define _COM_MEMCPY_S(dest,destsize,src,count) memcpy(dest,src,count)
  17
  18/* Use of wsprintf might be impossible, if strsafe.h is included. */
  19#ifndef __STDC_SECURE_LIB__
  20#define _COM_PRINTF_S_1(dest,destsize,format,arg1) wsprintf(dest,format,arg1)
  21#elif defined(UNICODE)
  22#define _COM_PRINTF_S_1(dest,destsize,format,arg1) swprintf_s(dest,destsize,format,arg1)
  23#else
  24#define _COM_PRINTF_S_1(dest,destsize,format,arg1) sprintf_s(dest,destsize,format,arg1)
  25#endif
  26
  27#ifdef __cplusplus
  28
  29#pragma push_macro("new")
  30#undef new
  31
  32#ifndef WINAPI
  33#if defined(_ARM_)
  34#define WINAPI
  35#else
  36#define WINAPI __stdcall
  37#endif
  38#endif
  39
  40class _com_error;
  41
  42void WINAPI _com_issue_error(HRESULT);
  43
  44class _bstr_t;
  45class _variant_t;
  46
  47namespace _com_util {
  48  inline void CheckError(HRESULT hr) {
  49    if(FAILED(hr)) { _com_issue_error(hr); }
  50  }
  51}
  52
  53namespace _com_util {
  54  BSTR WINAPI ConvertStringToBSTR(const char *pSrc);
  55  char *WINAPI ConvertBSTRToString(BSTR pSrc);
  56}
  57
  58class _bstr_t {
  59public:
  60  _bstr_t() throw();
  61  _bstr_t(const _bstr_t &s) throw();
  62  _bstr_t(const char *s);
  63  _bstr_t(const wchar_t *s);
  64  _bstr_t(const _variant_t &var);
  65  _bstr_t(BSTR bstr,bool fCopy);
  66  ~_bstr_t() throw();
  67  _bstr_t &operator=(const _bstr_t &s) throw();
  68  _bstr_t &operator=(const char *s);
  69  _bstr_t &operator=(const wchar_t *s);
  70  _bstr_t &operator=(const _variant_t &var);
  71  _bstr_t &operator+=(const _bstr_t &s);
  72  _bstr_t operator+(const _bstr_t &s) const;
  73  friend _bstr_t operator+(const char *s1,const _bstr_t &s2);
  74  friend _bstr_t operator+(const wchar_t *s1,const _bstr_t &s2);
  75  operator const wchar_t *() const throw();
  76  operator wchar_t *() const throw();
  77  operator const char *() const;
  78  operator char *() const;
  79  bool operator!() const throw();
  80  bool operator==(const _bstr_t &str) const throw();
  81  bool operator!=(const _bstr_t &str) const throw();
  82  bool operator<(const _bstr_t &str) const throw();
  83  bool operator>(const _bstr_t &str) const throw();
  84  bool operator<=(const _bstr_t &str) const throw();
  85  bool operator>=(const _bstr_t &str) const throw();
  86  BSTR copy(bool fCopy = true) const;
  87  unsigned int length() const throw();
  88  void Assign(BSTR s);
  89  BSTR &GetBSTR();
  90  BSTR *GetAddress();
  91  void Attach(BSTR s);
  92  BSTR Detach() throw();
  93private:
  94  class Data_t {
  95  public:
  96    Data_t(const char *s);
  97    Data_t(const wchar_t *s);
  98    Data_t(BSTR bstr,bool fCopy);
  99    Data_t(const _bstr_t &s1,const _bstr_t &s2);
 100    unsigned __LONG32 AddRef() throw();
 101    unsigned __LONG32 Release() throw();
 102    unsigned __LONG32 RefCount() const throw();
 103    operator const wchar_t *() const throw();
 104    operator const char *() const;
 105    const wchar_t *GetWString() const throw();
 106    wchar_t *&GetWString() throw();
 107    const char *GetString() const;
 108    BSTR Copy() const;
 109    void Assign(BSTR s);
 110    void Attach(BSTR s) throw();
 111    unsigned int Length() const throw();
 112    int Compare(const Data_t &str) const throw();
 113    void *operator new(size_t sz);
 114  private:
 115    BSTR m_wstr;
 116    mutable char *m_str;
 117    unsigned __LONG32 m_RefCount;
 118    Data_t() throw();
 119    Data_t(const Data_t &s) throw();
 120    ~Data_t() throw();
 121    void _Free() throw();
 122  };
 123private:
 124  Data_t *m_Data;
 125private:
 126  void _AddRef() throw();
 127  void _Free() throw();
 128  int _Compare(const _bstr_t &str) const throw();
 129};
 130
 131inline _bstr_t::_bstr_t() throw() : m_Data(NULL) { }
 132
 133inline _bstr_t::_bstr_t(const _bstr_t &s) throw() : m_Data(s.m_Data) { _AddRef(); }
 134
 135inline _bstr_t::_bstr_t(const char *s) : m_Data(new Data_t(s)) {
 136  if(!m_Data) { _com_issue_error(E_OUTOFMEMORY); }
 137}
 138
 139inline _bstr_t::_bstr_t(const wchar_t *s) : m_Data(new Data_t(s)) {
 140  if(!m_Data) { _com_issue_error(E_OUTOFMEMORY); }
 141}
 142
 143inline _bstr_t::_bstr_t(BSTR bstr,bool fCopy) : m_Data(new Data_t(bstr,fCopy)) {
 144  if(!m_Data) { _com_issue_error(E_OUTOFMEMORY); }
 145}
 146
 147inline _bstr_t::~_bstr_t() throw() { _Free(); }
 148
 149inline _bstr_t &_bstr_t::operator=(const _bstr_t &s) throw() {
 150  if(this!=&s) {
 151    _Free();
 152    m_Data = s.m_Data;
 153    _AddRef();
 154  }
 155  return *this;
 156}
 157
 158inline _bstr_t &_bstr_t::operator=(const char *s) {
 159  _COM_ASSERT(!s || static_cast<const char *>(*this)!=s);
 160  if(!s || static_cast<const char *>(*this)!=s) {
 161    _Free();
 162    m_Data = new Data_t(s);
 163    if(!m_Data) { _com_issue_error(E_OUTOFMEMORY); }
 164  }
 165  return *this;
 166}
 167
 168inline _bstr_t &_bstr_t::operator=(const wchar_t *s) {
 169  _COM_ASSERT(!s || static_cast<const wchar_t *>(*this)!=s);
 170  if(!s || static_cast<const wchar_t *>(*this)!=s) {
 171    _Free();
 172    m_Data = new Data_t(s);
 173    if(!m_Data) { _com_issue_error(E_OUTOFMEMORY); }
 174  }
 175  return *this;
 176}
 177
 178inline _bstr_t &_bstr_t::operator+=(const _bstr_t &s) {
 179  Data_t *newData = new Data_t(*this,s);
 180  if(!newData) { _com_issue_error(E_OUTOFMEMORY); }
 181  else {
 182    _Free();
 183    m_Data = newData;
 184  }
 185  return *this;
 186}
 187
 188inline _bstr_t _bstr_t::operator+(const _bstr_t &s) const {
 189  _bstr_t b = *this;
 190  b += s;
 191  return b;
 192}
 193
 194inline _bstr_t operator+(const char *s1,const _bstr_t &s2) {
 195  _bstr_t b = s1;
 196  b += s2;
 197  return b;
 198}
 199
 200inline _bstr_t operator+(const wchar_t *s1,const _bstr_t &s2) {
 201  _bstr_t b = s1;
 202  b += s2;
 203  return b;
 204}
 205
 206inline _bstr_t::operator const wchar_t *() const throw() { return (m_Data!=NULL) ? m_Data->GetWString() : NULL; }
 207inline _bstr_t::operator wchar_t *() const throw() { return const_cast<wchar_t *>((m_Data!=NULL) ? m_Data->GetWString() : NULL); }
 208inline _bstr_t::operator const char *() const { return (m_Data!=NULL) ? m_Data->GetString() : NULL; }
 209inline _bstr_t::operator char *() const { return const_cast<char *>((m_Data!=NULL) ? m_Data->GetString() : NULL); }
 210inline bool _bstr_t::operator!() const throw() { return (m_Data!=NULL) ? !m_Data->GetWString() : true; }
 211inline bool _bstr_t::operator==(const _bstr_t &str) const throw() { return _Compare(str)==0; }
 212inline bool _bstr_t::operator!=(const _bstr_t &str) const throw() { return _Compare(str)!=0; }
 213inline bool _bstr_t::operator<(const _bstr_t &str) const throw() { return _Compare(str)<0; }
 214inline bool _bstr_t::operator>(const _bstr_t &str) const throw() { return _Compare(str)>0; }
 215inline bool _bstr_t::operator<=(const _bstr_t &str) const throw() { return _Compare(str)<=0; }
 216inline bool _bstr_t::operator>=(const _bstr_t &str) const throw() { return _Compare(str)>=0; }
 217inline BSTR _bstr_t::copy(bool fCopy) const { return (m_Data!=NULL) ? (fCopy ? m_Data->Copy() : m_Data->GetWString()) : NULL; }
 218inline unsigned int _bstr_t::length() const throw() { return (m_Data!=NULL) ? m_Data->Length() : 0; }
 219inline void _bstr_t::Assign(BSTR s) {
 220  _COM_ASSERT(!s || !m_Data || m_Data->GetWString()!=s);
 221  if(!s || !m_Data || m_Data->GetWString()!=s) {
 222    _Free();
 223    m_Data = new Data_t(s,TRUE);
 224    if(!m_Data) { _com_issue_error(E_OUTOFMEMORY); }
 225  }
 226}
 227
 228inline BSTR &_bstr_t::GetBSTR() {
 229  if(!m_Data) {
 230    m_Data = new Data_t(0,FALSE);
 231    if(!m_Data) { _com_issue_error(E_OUTOFMEMORY); }
 232  }
 233  return m_Data->GetWString();
 234}
 235
 236inline BSTR *_bstr_t::GetAddress() {
 237  Attach(0);
 238  return &m_Data->GetWString();
 239}
 240
 241inline void _bstr_t::Attach(BSTR s) {
 242  _Free();
 243  m_Data = new Data_t(s,FALSE);
 244  if(!m_Data) { _com_issue_error(E_OUTOFMEMORY); }
 245}
 246
 247inline BSTR _bstr_t::Detach() throw () {
 248  _COM_ASSERT(m_Data!=NULL && m_Data->RefCount()==1);
 249  if(m_Data!=NULL && m_Data->RefCount()==1) {
 250    BSTR b = m_Data->GetWString();
 251    m_Data->GetWString() = NULL;
 252    _Free();
 253    return b;
 254  } else {
 255    _com_issue_error(E_POINTER);
 256    return NULL;
 257  }
 258}
 259
 260inline void _bstr_t::_AddRef() throw() {
 261  if(m_Data!=NULL) m_Data->AddRef();
 262}
 263
 264inline void _bstr_t::_Free() throw() {
 265  if(m_Data!=NULL) {
 266    m_Data->Release();
 267    m_Data = NULL;
 268  }
 269}
 270
 271inline int _bstr_t::_Compare(const _bstr_t &str) const throw() {
 272  if(m_Data==str.m_Data) return 0;
 273  if(!m_Data) return -1;
 274  if(!str.m_Data) return 1;
 275  return m_Data->Compare(*str.m_Data);
 276}
 277
 278inline _bstr_t::Data_t::Data_t(const char *s) : m_str(NULL),m_RefCount(1) {
 279  m_wstr = _com_util::ConvertStringToBSTR(s);
 280}
 281
 282inline _bstr_t::Data_t::Data_t(const wchar_t *s) : m_str(NULL),m_RefCount(1) {
 283  m_wstr = ::SysAllocString(s);
 284  if(!m_wstr && s!=NULL) { _com_issue_error(E_OUTOFMEMORY); }
 285}
 286
 287inline _bstr_t::Data_t::Data_t(BSTR bstr,bool fCopy) : m_str(NULL),m_RefCount(1) {
 288  if(fCopy && bstr!=NULL) {
 289    m_wstr = ::SysAllocStringByteLen(reinterpret_cast<char *>(bstr),::SysStringByteLen(bstr));
 290    if(!m_wstr) { _com_issue_error(E_OUTOFMEMORY); }
 291  } else m_wstr = bstr;
 292}
 293
 294inline _bstr_t::Data_t::Data_t(const _bstr_t &s1,const _bstr_t &s2) : m_str(NULL),m_RefCount(1) {
 295  const unsigned int l1 = s1.length();
 296  const unsigned int l2 = s2.length();
 297  m_wstr = ::SysAllocStringByteLen(NULL,(l1 + l2) *sizeof(wchar_t));
 298  if(!m_wstr) {
 299    _com_issue_error(E_OUTOFMEMORY);
 300    return;
 301  }
 302  const wchar_t *wstr1 = static_cast<const wchar_t *>(s1);
 303  if(wstr1!=NULL) {
 304    _COM_MEMCPY_S(m_wstr,(l1 + l2 + 1) *sizeof(wchar_t),wstr1,(l1 + 1) *sizeof(wchar_t));
 305  }
 306  const wchar_t *wstr2 = static_cast<const wchar_t *>(s2);
 307  if(wstr2!=NULL) {
 308    _COM_MEMCPY_S(m_wstr + l1,(l2 + 1) *sizeof(wchar_t),wstr2,(l2 + 1) *sizeof(wchar_t));
 309  }
 310}
 311
 312inline unsigned __LONG32 _bstr_t::Data_t::AddRef() throw() {
 313  InterlockedIncrement(reinterpret_cast<LONG*>(&m_RefCount));
 314  return m_RefCount;
 315}
 316
 317inline unsigned __LONG32 _bstr_t::Data_t::Release() throw() {
 318  unsigned __LONG32 cRef = InterlockedDecrement(reinterpret_cast<LONG*>(&m_RefCount));
 319  if(cRef==0) delete this;
 320  return cRef;
 321}
 322
 323inline unsigned __LONG32 _bstr_t::Data_t::RefCount() const throw() { return m_RefCount; }
 324inline _bstr_t::Data_t::operator const wchar_t *() const throw() { return m_wstr; }
 325inline _bstr_t::Data_t::operator const char *() const { return GetString(); }
 326inline const wchar_t *_bstr_t::Data_t::GetWString() const throw() { return m_wstr; }
 327inline wchar_t *&_bstr_t::Data_t::GetWString() throw() { return m_wstr; }
 328inline const char *_bstr_t::Data_t::GetString() const {
 329  if(!m_str) m_str = _com_util::ConvertBSTRToString(m_wstr);
 330  return m_str;
 331}
 332inline BSTR _bstr_t::Data_t::Copy() const {
 333  if(m_wstr!=NULL) {
 334    BSTR bstr = ::SysAllocStringByteLen(reinterpret_cast<char *>(m_wstr),::SysStringByteLen(m_wstr));
 335    if(!bstr) { _com_issue_error(E_OUTOFMEMORY); }
 336    return bstr;
 337  }
 338  return NULL;
 339}
 340inline void _bstr_t::Data_t::Assign(BSTR s) {
 341  _Free();
 342  if(s!=NULL) {
 343    m_wstr = ::SysAllocStringByteLen(reinterpret_cast<char *>(s),::SysStringByteLen(s));
 344    m_str = 0;
 345  }
 346}
 347inline void _bstr_t::Data_t::Attach(BSTR s) throw() {
 348  _Free();
 349  m_wstr = s;
 350  m_str = 0;
 351  m_RefCount = 1;
 352}
 353inline unsigned int _bstr_t::Data_t::Length() const throw() { return m_wstr ? ::SysStringLen(m_wstr) : 0; }
 354inline int _bstr_t::Data_t::Compare(const _bstr_t::Data_t &str) const throw() {
 355  if(!m_wstr) return str.m_wstr ? -1 : 0;
 356  if(!str.m_wstr) return 1;
 357  const unsigned int l1 = ::SysStringLen(m_wstr);
 358  const unsigned int l2 = ::SysStringLen(str.m_wstr);
 359  unsigned int len = l1;
 360  if(len>l2) len = l2;
 361  BSTR bstr1 = m_wstr;
 362  BSTR bstr2 = str.m_wstr;
 363  while (len-->0) {
 364    if(*bstr1++!=*bstr2++) return bstr1[-1] - bstr2[-1];
 365  }
 366  return (l1<l2) ? -1 : (l1==l2) ? 0 : 1;
 367}
 368
 369#ifdef _COM_OPERATOR_NEW_THROWS
 370inline void *_bstr_t::Data_t::operator new(size_t sz) {
 371  try {
 372    return ::operator new(sz);
 373  } catch (...) {
 374    return NULL;
 375  }
 376}
 377#else
 378inline void *_bstr_t::Data_t::operator new(size_t sz) {
 379  return ::operator new(sz);
 380}
 381#endif
 382
 383inline _bstr_t::Data_t::~Data_t() throw() { _Free(); }
 384inline void _bstr_t::Data_t::_Free() throw() {
 385  if(m_wstr!=NULL) ::SysFreeString(m_wstr);
 386  if(m_str!=NULL) delete [] m_str;
 387}
 388
 389class _variant_t : public ::tagVARIANT {
 390public:
 391  _variant_t() throw();
 392  _variant_t(const VARIANT &varSrc);
 393  _variant_t(const VARIANT *pSrc);
 394  _variant_t(const _variant_t &varSrc);
 395  _variant_t(VARIANT &varSrc,bool fCopy);
 396  _variant_t(short sSrc,VARTYPE vtSrc = VT_I2);
 397  _variant_t(__LONG32 lSrc,VARTYPE vtSrc = VT_I4);
 398  _variant_t(float fltSrc) throw();
 399  _variant_t(double dblSrc,VARTYPE vtSrc = VT_R8);
 400  _variant_t(const CY &cySrc) throw();
 401  _variant_t(const _bstr_t &bstrSrc);
 402  _variant_t(const wchar_t *pSrc);
 403  _variant_t(const char *pSrc);
 404  _variant_t(IDispatch *pSrc,bool fAddRef = true) throw();
 405  _variant_t(bool boolSrc) throw();
 406  _variant_t(IUnknown *pSrc,bool fAddRef = true) throw();
 407  _variant_t(const DECIMAL &decSrc) throw();
 408  _variant_t(BYTE bSrc) throw();
 409  _variant_t(char cSrc) throw();
 410  _variant_t(unsigned short usSrc) throw();
 411  _variant_t(unsigned __LONG32 ulSrc) throw();
 412#ifndef __CYGWIN__
 413  _variant_t(int iSrc) throw();
 414  _variant_t(unsigned int uiSrc) throw();
 415#endif
 416  __MINGW_EXTENSION _variant_t(__int64 i8Src) throw();
 417  __MINGW_EXTENSION _variant_t(unsigned __int64 ui8Src) throw();
 418  ~_variant_t() throw();
 419  operator short() const;
 420  operator __LONG32() const;
 421  operator float() const;
 422  operator double() const;
 423  operator CY() const;
 424  operator _bstr_t() const;
 425  operator IDispatch*() const;
 426  operator bool() const;
 427  operator IUnknown*() const;
 428  operator DECIMAL() const;
 429  operator BYTE() const;
 430  operator VARIANT() const throw();
 431  operator char() const;
 432  operator unsigned short() const;
 433  operator unsigned __LONG32() const;
 434#ifndef __CYGWIN__
 435  operator int() const;
 436  operator unsigned int() const;
 437#endif
 438  __MINGW_EXTENSION operator __int64() const;
 439  __MINGW_EXTENSION operator unsigned __int64() const;
 440  _variant_t &operator=(const VARIANT &varSrc);
 441  _variant_t &operator=(const VARIANT *pSrc);
 442  _variant_t &operator=(const _variant_t &varSrc);
 443  _variant_t &operator=(short sSrc);
 444  _variant_t &operator=(__LONG32 lSrc);
 445  _variant_t &operator=(float fltSrc);
 446  _variant_t &operator=(double dblSrc);
 447  _variant_t &operator=(const CY &cySrc);
 448  _variant_t &operator=(const _bstr_t &bstrSrc);
 449  _variant_t &operator=(const wchar_t *pSrc);
 450  _variant_t &operator=(const char *pSrc);
 451  _variant_t &operator=(IDispatch *pSrc);
 452  _variant_t &operator=(bool boolSrc);
 453  _variant_t &operator=(IUnknown *pSrc);
 454  _variant_t &operator=(const DECIMAL &decSrc);
 455  _variant_t &operator=(BYTE bSrc);
 456  _variant_t &operator=(char cSrc);
 457  _variant_t &operator=(unsigned short usSrc);
 458  _variant_t &operator=(unsigned __LONG32 ulSrc);
 459#ifndef __CYGWIN__
 460  _variant_t &operator=(int iSrc);
 461  _variant_t &operator=(unsigned int uiSrc);
 462#endif
 463  __MINGW_EXTENSION _variant_t &operator=(__int64 i8Src);
 464  __MINGW_EXTENSION _variant_t &operator=(unsigned __int64 ui8Src);
 465  bool operator==(const VARIANT &varSrc) const throw();
 466  bool operator==(const VARIANT *pSrc) const throw();
 467  bool operator!=(const VARIANT &varSrc) const throw();
 468  bool operator!=(const VARIANT *pSrc) const throw();
 469  void Clear();
 470  void Attach(VARIANT &varSrc);
 471  VARIANT Detach();
 472  VARIANT &GetVARIANT() throw();
 473  VARIANT *GetAddress();
 474  void ChangeType(VARTYPE vartype,const _variant_t *pSrc = NULL);
 475  void SetString(const char *pSrc);
 476};
 477
 478inline _variant_t::_variant_t() throw() { ::VariantInit(this); }
 479inline _variant_t::_variant_t(const VARIANT &varSrc) {
 480  ::VariantInit(this);
 481  _com_util::CheckError(::VariantCopy(this,const_cast<VARIANT*>(&varSrc)));
 482}
 483inline _variant_t::_variant_t(const VARIANT *pSrc) {
 484  if(!pSrc) { _com_issue_error(E_POINTER); }
 485  else {
 486    ::VariantInit(this);
 487    _com_util::CheckError(::VariantCopy(this,const_cast<VARIANT*>(pSrc)));
 488  }
 489}
 490inline _variant_t::_variant_t(const _variant_t &varSrc) {
 491  ::VariantInit(this);
 492  _com_util::CheckError(::VariantCopy(this,const_cast<VARIANT*>(static_cast<const VARIANT*>(&varSrc))));
 493}
 494inline _variant_t::_variant_t(VARIANT &varSrc,bool fCopy) {
 495  if(fCopy) {
 496    ::VariantInit(this);
 497    _com_util::CheckError(::VariantCopy(this,&varSrc));
 498  } else {
 499    _COM_MEMCPY_S(this,sizeof(varSrc),&varSrc,sizeof(varSrc));
 500    V_VT(&varSrc) = VT_EMPTY;
 501  }
 502}
 503inline _variant_t::_variant_t(short sSrc,VARTYPE vtSrc) {
 504  if((vtSrc!=VT_I2) && (vtSrc!=VT_BOOL)) {
 505    _com_issue_error(E_INVALIDARG);
 506    return;
 507  }
 508  if(vtSrc==VT_BOOL) {
 509    V_VT(this) = VT_BOOL;
 510    V_BOOL(this) = (sSrc ? VARIANT_TRUE : VARIANT_FALSE);
 511  } else {
 512    V_VT(this) = VT_I2;
 513    V_I2(this) = sSrc;
 514  }
 515}
 516inline _variant_t::_variant_t(__LONG32 lSrc,VARTYPE vtSrc) {
 517  if((vtSrc!=VT_I4) && (vtSrc!=VT_ERROR) && (vtSrc!=VT_BOOL)) {
 518    _com_issue_error(E_INVALIDARG);
 519    return;
 520  }
 521  if(vtSrc==VT_ERROR) {
 522    V_VT(this) = VT_ERROR;
 523    V_ERROR(this) = lSrc;
 524  } else if(vtSrc==VT_BOOL) {
 525    V_VT(this) = VT_BOOL;
 526    V_BOOL(this) = (lSrc ? VARIANT_TRUE : VARIANT_FALSE);
 527  } else {
 528    V_VT(this) = VT_I4;
 529    V_I4(this) = lSrc;
 530  }
 531}
 532inline _variant_t::_variant_t(float fltSrc) throw() {
 533  V_VT(this) = VT_R4;
 534  V_R4(this) = fltSrc;
 535}
 536
 537inline _variant_t::_variant_t(double dblSrc,VARTYPE vtSrc) {
 538  if((vtSrc!=VT_R8) && (vtSrc!=VT_DATE)) {
 539    _com_issue_error(E_INVALIDARG);
 540    return;
 541  }
 542  if(vtSrc==VT_DATE) {
 543    V_VT(this) = VT_DATE;
 544    V_DATE(this) = dblSrc;
 545  } else {
 546    V_VT(this) = VT_R8;
 547    V_R8(this) = dblSrc;
 548  }
 549}
 550inline _variant_t::_variant_t(const CY &cySrc) throw() {
 551  V_VT(this) = VT_CY;
 552  V_CY(this) = cySrc;
 553}
 554inline _variant_t::_variant_t(const _bstr_t &bstrSrc) {
 555  V_VT(this) = VT_BSTR;
 556  BSTR bstr = static_cast<wchar_t *>(bstrSrc);
 557  if(!bstr) V_BSTR(this) = NULL;
 558  else {
 559    V_BSTR(this) = ::SysAllocStringByteLen(reinterpret_cast<char *>(bstr),::SysStringByteLen(bstr));
 560    if(!(V_BSTR(this))) { _com_issue_error(E_OUTOFMEMORY); }
 561  }
 562}
 563inline _variant_t::_variant_t(const wchar_t *pSrc) {
 564  V_VT(this) = VT_BSTR;
 565  V_BSTR(this) = ::SysAllocString(pSrc);
 566  if(!(V_BSTR(this)) && pSrc!=NULL) { _com_issue_error(E_OUTOFMEMORY); }
 567}
 568inline _variant_t::_variant_t(const char *pSrc) {
 569  V_VT(this) = VT_BSTR;
 570  V_BSTR(this) = _com_util::ConvertStringToBSTR(pSrc);
 571}
 572inline _variant_t::_variant_t(IDispatch *pSrc,bool fAddRef) throw() {
 573  V_VT(this) = VT_DISPATCH;
 574  V_DISPATCH(this) = pSrc;
 575  if(fAddRef && V_DISPATCH(this)!=NULL) V_DISPATCH(this)->AddRef();
 576}
 577inline _variant_t::_variant_t(bool boolSrc) throw() {
 578  V_VT(this) = VT_BOOL;
 579  V_BOOL(this) = (boolSrc ? VARIANT_TRUE : VARIANT_FALSE);
 580}
 581inline _variant_t::_variant_t(IUnknown *pSrc,bool fAddRef) throw() {
 582  V_VT(this) = VT_UNKNOWN;
 583  V_UNKNOWN(this) = pSrc;
 584  if(fAddRef && V_UNKNOWN(this)!=NULL) V_UNKNOWN(this)->AddRef();
 585}
 586inline _variant_t::_variant_t(const DECIMAL &decSrc) throw() {
 587  V_DECIMAL(this) = decSrc;
 588  V_VT(this) = VT_DECIMAL;
 589}
 590inline _variant_t::_variant_t(BYTE bSrc) throw() {
 591  V_VT(this) = VT_UI1;
 592  V_UI1(this) = bSrc;
 593}
 594inline _variant_t::_variant_t(char cSrc) throw() {
 595  V_VT(this) = VT_I1;
 596  V_I1(this) = cSrc;
 597}
 598inline _variant_t::_variant_t(unsigned short usSrc) throw() {
 599  V_VT(this) = VT_UI2;
 600  V_UI2(this) = usSrc;
 601}
 602inline _variant_t::_variant_t(unsigned __LONG32 ulSrc) throw() {
 603  V_VT(this) = VT_UI4;
 604  V_UI4(this) = ulSrc;
 605}
 606#ifndef __CYGWIN__
 607inline _variant_t::_variant_t(int iSrc) throw() {
 608  V_VT(this) = VT_INT;
 609  V_INT(this) = iSrc;
 610}
 611inline _variant_t::_variant_t(unsigned int uiSrc) throw() {
 612  V_VT(this) = VT_UINT;
 613  V_UINT(this) = uiSrc;
 614}
 615#endif
 616__MINGW_EXTENSION inline _variant_t::_variant_t(__int64 i8Src) throw() {
 617  V_VT(this) = VT_I8;
 618  V_I8(this) = i8Src;
 619}
 620__MINGW_EXTENSION inline _variant_t::_variant_t(unsigned __int64 ui8Src) throw() {
 621  V_VT(this) = VT_UI8;
 622  V_UI8(this) = ui8Src;
 623}
 624inline _variant_t::operator short() const {
 625  if(V_VT(this)==VT_I2) return V_I2(this);
 626  _variant_t varDest;
 627  varDest.ChangeType(VT_I2,this);
 628  return V_I2(&varDest);
 629}
 630inline _variant_t::operator __LONG32() const {
 631  if(V_VT(this)==VT_I4) return V_I4(this);
 632  _variant_t varDest;
 633  varDest.ChangeType(VT_I4,this);
 634  return V_I4(&varDest);
 635}
 636
 637inline _variant_t::operator float() const {
 638  if(V_VT(this)==VT_R4) return V_R4(this);
 639  _variant_t varDest;
 640  varDest.ChangeType(VT_R4,this);
 641  return V_R4(&varDest);
 642}
 643
 644inline _variant_t::operator double() const {
 645  if(V_VT(this)==VT_R8) return V_R8(this);
 646  _variant_t varDest;
 647  varDest.ChangeType(VT_R8,this);
 648  return V_R8(&varDest);
 649}
 650
 651inline _variant_t::operator CY() const {
 652  if(V_VT(this)==VT_CY) return V_CY(this);
 653  _variant_t varDest;
 654  varDest.ChangeType(VT_CY,this);
 655  return V_CY(&varDest);
 656}
 657
 658inline _variant_t::operator _bstr_t() const {
 659  if(V_VT(this)==VT_BSTR) return V_BSTR(this);
 660  _variant_t varDest;
 661  varDest.ChangeType(VT_BSTR,this);
 662  return V_BSTR(&varDest);
 663}
 664
 665inline _variant_t::operator IDispatch*() const {
 666  if(V_VT(this)==VT_DISPATCH) {
 667    if(V_DISPATCH(this)!=NULL) V_DISPATCH(this)->AddRef();
 668    return V_DISPATCH(this);
 669  }
 670  _variant_t varDest;
 671  varDest.ChangeType(VT_DISPATCH,this);
 672  if(V_DISPATCH(&varDest)!=NULL) V_DISPATCH(&varDest)->AddRef();
 673  return V_DISPATCH(&varDest);
 674}
 675inline _variant_t::operator bool() const {
 676  if(V_VT(this)==VT_BOOL) return V_BOOL(this) ? true : false;
 677  _variant_t varDest;
 678  varDest.ChangeType(VT_BOOL,this);
 679  return (V_BOOL(&varDest)==VARIANT_TRUE) ? true : false;
 680}
 681
 682inline _variant_t::operator IUnknown*() const {
 683  if(V_VT(this)==VT_UNKNOWN) {
 684    if(V_UNKNOWN(this)!=NULL) V_UNKNOWN(this)->AddRef();
 685    return V_UNKNOWN(this);
 686  }
 687  _variant_t varDest;
 688  varDest.ChangeType(VT_UNKNOWN,this);
 689  if(V_UNKNOWN(&varDest)!=NULL) V_UNKNOWN(&varDest)->AddRef();
 690  return V_UNKNOWN(&varDest);
 691}
 692inline _variant_t::operator DECIMAL() const {
 693  if(V_VT(this)==VT_DECIMAL) return V_DECIMAL(this);
 694  _variant_t varDest;
 695  varDest.ChangeType(VT_DECIMAL,this);
 696  return V_DECIMAL(&varDest);
 697}
 698inline _variant_t::operator BYTE() const {
 699  if(V_VT(this)==VT_UI1) return V_UI1(this);
 700  _variant_t varDest;
 701  varDest.ChangeType(VT_UI1,this);
 702  return V_UI1(&varDest);
 703}
 704inline _variant_t::operator VARIANT() const throw() { return *(VARIANT*) this; }
 705inline _variant_t::operator char() const {
 706  if(V_VT(this)==VT_I1) return V_I1(this);
 707  _variant_t varDest;
 708  varDest.ChangeType(VT_I1,this);
 709  return V_I1(&varDest);
 710}
 711
 712inline _variant_t::operator unsigned short() const {
 713  if(V_VT(this)==VT_UI2) return V_UI2(this);
 714  _variant_t varDest;
 715  varDest.ChangeType(VT_UI2,this);
 716  return V_UI2(&varDest);
 717}
 718
 719inline _variant_t::operator unsigned __LONG32() const {
 720  if(V_VT(this)==VT_UI4) return V_UI4(this);
 721  _variant_t varDest;
 722  varDest.ChangeType(VT_UI4,this);
 723  return V_UI4(&varDest);
 724}
 725#ifndef __CYGWIN__
 726inline _variant_t::operator int() const {
 727  if(V_VT(this)==VT_INT) return V_INT(this);
 728  _variant_t varDest;
 729  varDest.ChangeType(VT_INT,this);
 730  return V_INT(&varDest);
 731}
 732inline _variant_t::operator unsigned int() const {
 733  if(V_VT(this)==VT_UINT) return V_UINT(this);
 734  _variant_t varDest;
 735  varDest.ChangeType(VT_UINT,this);
 736  return V_UINT(&varDest);
 737}
 738#endif
 739__MINGW_EXTENSION inline _variant_t::operator __int64() const {
 740  if(V_VT(this)==VT_I8) return V_I8(this);
 741  _variant_t varDest;
 742  varDest.ChangeType(VT_I8,this);
 743  return V_I8(&varDest);
 744}
 745__MINGW_EXTENSION inline _variant_t::operator unsigned __int64() const {
 746  if(V_VT(this)==VT_UI8) return V_UI8(this);
 747  _variant_t varDest;
 748  varDest.ChangeType(VT_UI8,this);
 749  return V_UI8(&varDest);
 750}
 751inline _variant_t &_variant_t::operator=(const VARIANT &varSrc) {
 752  _com_util::CheckError(::VariantCopy(this,const_cast<VARIANT*>(&varSrc)));
 753  return *this;
 754}
 755inline _variant_t &_variant_t::operator=(const VARIANT *pSrc) {
 756  if(!pSrc) { _com_issue_error(E_POINTER); }
 757  else { _com_util::CheckError(::VariantCopy(this,const_cast<VARIANT*>(pSrc))); }
 758  return *this;
 759}
 760inline _variant_t &_variant_t::operator=(const _variant_t &varSrc) {
 761  _com_util::CheckError(::VariantCopy(this,const_cast<VARIANT*>(static_cast<const VARIANT*>(&varSrc))));
 762  return *this;
 763}
 764inline _variant_t &_variant_t::operator=(short sSrc) {
 765  if(V_VT(this)==VT_I2) V_I2(this) = sSrc;
 766  else if(V_VT(this)==VT_BOOL) V_BOOL(this) = (sSrc ? VARIANT_TRUE : VARIANT_FALSE);
 767  else {
 768    Clear();
 769    V_VT(this) = VT_I2;
 770    V_I2(this) = sSrc;
 771  }
 772  return *this;
 773}
 774inline _variant_t &_variant_t::operator=(__LONG32 lSrc) {
 775  if(V_VT(this)==VT_I4) V_I4(this) = lSrc;
 776  else if(V_VT(this)==VT_ERROR) V_ERROR(this) = lSrc;
 777  else if(V_VT(this)==VT_BOOL) V_BOOL(this) = (lSrc ? VARIANT_TRUE : VARIANT_FALSE);
 778  else {
 779    Clear();
 780    V_VT(this) = VT_I4;
 781    V_I4(this) = lSrc;
 782  }
 783  return *this;
 784}
 785inline _variant_t &_variant_t::operator=(float fltSrc) {
 786  if(V_VT(this)!=VT_R4) {
 787    Clear();
 788    V_VT(this) = VT_R4;
 789  }
 790  V_R4(this) = fltSrc;
 791  return *this;
 792}
 793
 794inline _variant_t &_variant_t::operator=(double dblSrc)
 795{
 796  if(V_VT(this)==VT_R8) {
 797    V_R8(this) = dblSrc;
 798  }
 799  else if(V_VT(this)==VT_DATE) {
 800    V_DATE(this) = dblSrc;
 801  }
 802  else {
 803
 804    Clear();
 805
 806    V_VT(this) = VT_R8;
 807    V_R8(this) = dblSrc;
 808  }
 809
 810  return *this;
 811}
 812
 813inline _variant_t &_variant_t::operator=(const CY &cySrc)
 814{
 815  if(V_VT(this)!=VT_CY) {
 816
 817    Clear();
 818
 819    V_VT(this) = VT_CY;
 820  }
 821
 822  V_CY(this) = cySrc;
 823
 824  return *this;
 825}
 826
 827inline _variant_t &_variant_t::operator=(const _bstr_t &bstrSrc)
 828{
 829  _COM_ASSERT(V_VT(this)!=VT_BSTR || !((BSTR) bstrSrc) || V_BSTR(this)!=(BSTR) bstrSrc);
 830
 831  Clear();
 832
 833  V_VT(this) = VT_BSTR;
 834
 835  if(!bstrSrc) {
 836    V_BSTR(this) = NULL;
 837  }
 838  else {
 839    BSTR bstr = static_cast<wchar_t *>(bstrSrc);
 840    V_BSTR(this) = ::SysAllocStringByteLen(reinterpret_cast<char *>(bstr),::SysStringByteLen(bstr));
 841
 842    if(!(V_BSTR(this))) {
 843      _com_issue_error(E_OUTOFMEMORY);
 844    }
 845  }
 846
 847  return *this;
 848}
 849
 850inline _variant_t &_variant_t::operator=(const wchar_t *pSrc)
 851{
 852  _COM_ASSERT(V_VT(this)!=VT_BSTR || !pSrc || V_BSTR(this)!=pSrc);
 853
 854  Clear();
 855
 856  V_VT(this) = VT_BSTR;
 857
 858  if(!pSrc) {
 859    V_BSTR(this) = NULL;
 860  }
 861  else {
 862    V_BSTR(this) = ::SysAllocString(pSrc);
 863
 864    if(!(V_BSTR(this))) {
 865      _com_issue_error(E_OUTOFMEMORY);
 866    }
 867  }
 868
 869  return *this;
 870}
 871
 872inline _variant_t &_variant_t::operator=(const char *pSrc)
 873{
 874  _COM_ASSERT(V_VT(this)!=(VT_I1 | VT_BYREF) || !pSrc || V_I1REF(this)!=pSrc);
 875
 876  Clear();
 877
 878  V_VT(this) = VT_BSTR;
 879  V_BSTR(this) = _com_util::ConvertStringToBSTR(pSrc);
 880
 881  return *this;
 882}
 883
 884inline _variant_t &_variant_t::operator=(IDispatch *pSrc)
 885{
 886  _COM_ASSERT(V_VT(this)!=VT_DISPATCH || pSrc==0 || V_DISPATCH(this)!=pSrc);
 887
 888  Clear();
 889
 890  V_VT(this) = VT_DISPATCH;
 891  V_DISPATCH(this) = pSrc;
 892
 893  if(V_DISPATCH(this)!=NULL) {
 894
 895    V_DISPATCH(this)->AddRef();
 896  }
 897
 898  return *this;
 899}
 900
 901inline _variant_t &_variant_t::operator=(bool boolSrc)
 902{
 903  if(V_VT(this)!=VT_BOOL) {
 904
 905    Clear();
 906
 907    V_VT(this) = VT_BOOL;
 908  }
 909
 910  V_BOOL(this) = (boolSrc ? VARIANT_TRUE : VARIANT_FALSE);
 911
 912  return *this;
 913}
 914
 915inline _variant_t &_variant_t::operator=(IUnknown *pSrc)
 916{
 917  _COM_ASSERT(V_VT(this)!=VT_UNKNOWN || !pSrc || V_UNKNOWN(this)!=pSrc);
 918
 919  Clear();
 920
 921  V_VT(this) = VT_UNKNOWN;
 922  V_UNKNOWN(this) = pSrc;
 923
 924  if(V_UNKNOWN(this)!=NULL) {
 925
 926    V_UNKNOWN(this)->AddRef();
 927  }
 928
 929  return *this;
 930}
 931
 932inline _variant_t &_variant_t::operator=(const DECIMAL &decSrc)
 933{
 934  if(V_VT(this)!=VT_DECIMAL) {
 935
 936    Clear();
 937  }
 938
 939  V_DECIMAL(this) = decSrc;
 940  V_VT(this) = VT_DECIMAL;
 941
 942  return *this;
 943}
 944
 945inline _variant_t &_variant_t::operator=(BYTE bSrc)
 946{
 947  if(V_VT(this)!=VT_UI1) {
 948
 949    Clear();
 950
 951    V_VT(this) = VT_UI1;
 952  }
 953
 954  V_UI1(this) = bSrc;
 955
 956  return *this;
 957}
 958
 959inline _variant_t &_variant_t::operator=(char cSrc)
 960{
 961  if(V_VT(this)!=VT_I1) {
 962
 963    Clear();
 964
 965    V_VT(this) = VT_I1;
 966  }
 967
 968  V_I1(this) = cSrc;
 969
 970  return *this;
 971}
 972
 973inline _variant_t &_variant_t::operator=(unsigned short usSrc)
 974{
 975  if(V_VT(this)!=VT_UI2) {
 976
 977    Clear();
 978
 979    V_VT(this) = VT_UI2;
 980  }
 981
 982  V_UI2(this) = usSrc;
 983
 984  return *this;
 985}
 986
 987inline _variant_t &_variant_t::operator=(unsigned __LONG32 ulSrc)
 988{
 989  if(V_VT(this)!=VT_UI4) {
 990
 991    Clear();
 992
 993    V_VT(this) = VT_UI4;
 994  }
 995
 996  V_UI4(this) = ulSrc;
 997
 998  return *this;
 999}
1000
1001#ifndef __CYGWIN__
1002inline _variant_t &_variant_t::operator=(int iSrc)
1003{
1004  if(V_VT(this)!=VT_INT) {
1005
1006    Clear();
1007
1008    V_VT(this) = VT_INT;
1009  }
1010
1011  V_INT(this) = iSrc;
1012
1013  return *this;
1014}
1015
1016inline _variant_t &_variant_t::operator=(unsigned int uiSrc)
1017{
1018  if(V_VT(this)!=VT_UINT) {
1019
1020    Clear();
1021
1022    V_VT(this) = VT_UINT;
1023  }
1024
1025  V_UINT(this) = uiSrc;
1026
1027  return *this;
1028}
1029#endif
1030
1031__MINGW_EXTENSION inline _variant_t &_variant_t::operator=(__int64 i8Src) {
1032  if(V_VT(this)!=VT_I8) {
1033
1034    Clear();
1035
1036    V_VT(this) = VT_I8;
1037  }
1038
1039  V_I8(this) = i8Src;
1040
1041  return *this;
1042}
1043
1044__MINGW_EXTENSION inline _variant_t &_variant_t::operator=(unsigned __int64 ui8Src) {
1045  if(V_VT(this)!=VT_UI8) {
1046
1047    Clear();
1048
1049    V_VT(this) = VT_UI8;
1050  }
1051
1052  V_UI8(this) = ui8Src;
1053
1054  return *this;
1055}
1056
1057inline bool _variant_t::operator==(const VARIANT &varSrc) const throw() {
1058  return *this==&varSrc;
1059}
1060
1061inline bool _variant_t::operator==(const VARIANT *pSrc) const throw()
1062{
1063  if(!pSrc) {
1064    return false;
1065  }
1066
1067  if(this==pSrc) {
1068    return true;
1069  }
1070
1071  if(V_VT(this)!=V_VT(pSrc)) {
1072    return false;
1073  }
1074
1075  switch (V_VT(this)) {
1076case VT_EMPTY:
1077case VT_NULL:
1078  return true;
1079
1080case VT_I2:
1081  return V_I2(this)==V_I2(pSrc);
1082
1083case VT_I4:
1084  return V_I4(this)==V_I4(pSrc);
1085
1086case VT_R4:
1087  return V_R4(this)==V_R4(pSrc);
1088
1089case VT_R8:
1090  return V_R8(this)==V_R8(pSrc);
1091
1092case VT_CY:
1093  return memcmp(&(V_CY(this)),&(V_CY(pSrc)),sizeof(CY))==0;
1094
1095case VT_DATE:
1096  return V_DATE(this)==V_DATE(pSrc);
1097
1098case VT_BSTR:
1099  return (::SysStringByteLen(V_BSTR(this))==::SysStringByteLen(V_BSTR(pSrc))) &&
1100    (memcmp(V_BSTR(this),V_BSTR(pSrc),::SysStringByteLen(V_BSTR(this)))==0);
1101
1102case VT_DISPATCH:
1103  return V_DISPATCH(this)==V_DISPATCH(pSrc);
1104
1105case VT_ERROR:
1106  return V_ERROR(this)==V_ERROR(pSrc);
1107
1108case VT_BOOL:
1109  return V_BOOL(this)==V_BOOL(pSrc);
1110
1111case VT_UNKNOWN:
1112  return V_UNKNOWN(this)==V_UNKNOWN(pSrc);
1113
1114case VT_DECIMAL:
1115  return memcmp(&(V_DECIMAL(this)),&(V_DECIMAL(pSrc)),sizeof(DECIMAL))==0;
1116
1117case VT_UI1:
1118  return V_UI1(this)==V_UI1(pSrc);
1119
1120case VT_I1:
1121  return V_I1(this)==V_I1(pSrc);
1122
1123case VT_UI2:
1124  return V_UI2(this)==V_UI2(pSrc);
1125
1126case VT_UI4:
1127  return V_UI4(this)==V_UI4(pSrc);
1128
1129case VT_INT:
1130  return V_INT(this)==V_INT(pSrc);
1131
1132case VT_UINT:
1133  return V_UINT(this)==V_UINT(pSrc);
1134
1135case VT_I8:
1136  return V_I8(this)==V_I8(pSrc);
1137
1138case VT_UI8:
1139  return V_UI8(this)==V_UI8(pSrc);
1140
1141default:
1142  _com_issue_error(E_INVALIDARG);
1143
1144  }
1145
1146  return false;
1147}
1148
1149inline bool _variant_t::operator!=(const VARIANT &varSrc) const throw()
1150{
1151  return !(*this==&varSrc);
1152}
1153
1154inline bool _variant_t::operator!=(const VARIANT *pSrc) const throw()
1155{
1156  return !(*this==pSrc);
1157}
1158
1159inline void _variant_t::Clear()
1160{
1161  _com_util::CheckError(::VariantClear(this));
1162}
1163
1164inline void _variant_t::Attach(VARIANT &varSrc)
1165{
1166
1167  Clear();
1168
1169  _COM_MEMCPY_S(this,sizeof(varSrc),&varSrc,sizeof(varSrc));
1170  V_VT(&varSrc) = VT_EMPTY;
1171}
1172
1173inline VARIANT _variant_t::Detach()
1174{
1175  VARIANT varResult = *this;
1176  V_VT(this) = VT_EMPTY;
1177
1178  return varResult;
1179}
1180
1181inline VARIANT &_variant_t::GetVARIANT() throw()
1182{
1183  return *(VARIANT*) this;
1184}
1185
1186inline VARIANT *_variant_t::GetAddress() {
1187  Clear();
1188  return (VARIANT*) this;
1189}
1190inline void _variant_t::ChangeType(VARTYPE vartype,const _variant_t *pSrc) {
1191  if(!pSrc) pSrc = this;
1192  if((this!=pSrc) || (vartype!=V_VT(this))) {
1193    _com_util::CheckError(::VariantChangeType(static_cast<VARIANT*>(this),const_cast<VARIANT*>(static_cast<const VARIANT*>(pSrc)),0,vartype));
1194  }
1195}
1196inline void _variant_t::SetString(const char *pSrc) { operator=(pSrc); }
1197inline _variant_t::~_variant_t() throw() { ::VariantClear(this); }
1198inline _bstr_t::_bstr_t(const _variant_t &var) : m_Data(NULL) {
1199  if(V_VT(&var)==VT_BSTR) {
1200    *this = V_BSTR(&var);
1201    return;
1202  }
1203  _variant_t varDest;
1204  varDest.ChangeType(VT_BSTR,&var);
1205  *this = V_BSTR(&varDest);
1206}
1207inline _bstr_t &_bstr_t::operator=(const _variant_t &var) {
1208  if(V_VT(&var)==VT_BSTR) {
1209    *this = V_BSTR(&var);
1210    return *this;
1211  }
1212  _variant_t varDest;
1213  varDest.ChangeType(VT_BSTR,&var);
1214  *this = V_BSTR(&varDest);
1215  return *this;
1216}
1217
1218extern _variant_t vtMissing;
1219
1220#ifndef _USE_RAW
1221#define bstr_t _bstr_t
1222#define variant_t _variant_t
1223#endif
1224
1225#pragma pop_macro("new")
1226
1227/* We use _com_issue_error here, but we only provide its inline version in comdef.h,
1228 * so we need to make sure that it's included as well. */
1229#include <comdef.h>
1230
1231#endif /* __cplusplus */
1232
1233#endif