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