• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // MyCom.h
2 
3 #ifndef ZIP7_INC_MY_COM_H
4 #define ZIP7_INC_MY_COM_H
5 
6 #include "MyWindows.h"
7 #include "MyTypes.h"
8 
9 template <class T>
10 class CMyComPtr
11 {
12   T* _p;
13 public:
CMyComPtr()14   CMyComPtr(): _p(NULL) {}
throw()15   CMyComPtr(T* p) throw() { if ((_p = p) != NULL) p->AddRef(); }
throw()16   CMyComPtr(const CMyComPtr<T>& lp) throw() { if ((_p = lp._p) != NULL) _p->AddRef(); }
~CMyComPtr()17   ~CMyComPtr() { if (_p) _p->Release(); }
Release()18   void Release() { if (_p) { _p->Release(); _p = NULL; } }
19   operator T*() const {  return (T*)_p;  }
20   // T& operator*() const {  return *_p; }
21   T** operator&() { return &_p; }
22   T* operator->() const { return _p; }
23   T* operator=(T* p)
24   {
25     if (p)
26       p->AddRef();
27     if (_p)
28       _p->Release();
29     _p = p;
30     return p;
31   }
32   T* operator=(const CMyComPtr<T>& lp) { return (*this = lp._p); }
33   bool operator!() const { return (_p == NULL); }
34   // bool operator==(T* pT) const {  return _p == pT; }
Attach(T * p2)35   void Attach(T* p2)
36   {
37     Release();
38     _p = p2;
39   }
Detach()40   T* Detach()
41   {
42     T* pt = _p;
43     _p = NULL;
44     return pt;
45   }
46   #ifdef _WIN32
47   HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
48   {
49     return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p);
50   }
51   #endif
52   /*
53   HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
54   {
55     CLSID clsid;
56     HRESULT hr = CLSIDFromProgID(szProgID, &clsid);
57     ATLASSERT(_p == NULL);
58     if (SUCCEEDED(hr))
59       hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p);
60     return hr;
61   }
62   */
63   template <class Q>
QueryInterface(REFGUID iid,Q ** pp)64   HRESULT QueryInterface(REFGUID iid, Q** pp) const throw()
65   {
66     // if (*pp) throw 20220216; // for debug
67     return _p->QueryInterface(iid, (void**)pp);
68   }
69 };
70 
71 #define Z7_DECL_CMyComPtr_QI_FROM(i, v, unk) \
72   CMyComPtr<i> v; (unk)->QueryInterface(IID_ ## i, (void **)&v);
73 
74 
75 //////////////////////////////////////////////////////////
76 
StringToBstr(LPCOLESTR src,BSTR * bstr)77 inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr)
78 {
79   *bstr = ::SysAllocString(src);
80   return (*bstr) ? S_OK : E_OUTOFMEMORY;
81 }
82 
83 class CMyComBSTR
84 {
85   BSTR m_str;
Z7_CLASS_NO_COPY(CMyComBSTR)86   Z7_CLASS_NO_COPY(CMyComBSTR)
87 public:
88   CMyComBSTR(): m_str(NULL) {}
~CMyComBSTR()89   ~CMyComBSTR() { ::SysFreeString(m_str); }
90   BSTR* operator&() { return &m_str; }
LPCOLESTR()91   operator LPCOLESTR() const { return m_str; }
92   // operator bool() const { return m_str != NULL; }
93   // bool operator!() const { return m_str == NULL; }
94 
Wipe_and_Free()95   void Wipe_and_Free()
96   {
97     if (m_str)
98     {
99       memset(m_str, 0, ::SysStringLen(m_str) * sizeof(*m_str));
100       Empty();
101     }
102   }
103 
104 private:
105   // operator BSTR() const { return m_str; }
106 
CMyComBSTR(LPCOLESTR src)107   CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); }
108   // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); }
109   // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize);  }
110   // CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); }
111 
112   /*
113   CMyComBSTR(REFGUID src)
114   {
115     LPOLESTR szGuid;
116     StringFromCLSID(src, &szGuid);
117     m_str = ::SysAllocString(szGuid);
118     CoTaskMemFree(szGuid);
119   }
120   */
121 
122   /*
123   CMyComBSTR& operator=(const CMyComBSTR& src)
124   {
125     if (m_str != src.m_str)
126     {
127       if (m_str)
128         ::SysFreeString(m_str);
129       m_str = src.MyCopy();
130     }
131     return *this;
132   }
133   */
134 
135   CMyComBSTR& operator=(LPCOLESTR src)
136   {
137     ::SysFreeString(m_str);
138     m_str = ::SysAllocString(src);
139     return *this;
140   }
141 
Len()142   unsigned Len() const { return ::SysStringLen(m_str); }
143 
MyCopy()144   BSTR MyCopy() const
145   {
146     // We don't support Byte BSTRs here
147     return ::SysAllocStringLen(m_str, ::SysStringLen(m_str));
148     /*
149     UINT byteLen = ::SysStringByteLen(m_str);
150     BSTR res = ::SysAllocStringByteLen(NULL, byteLen);
151     if (res && byteLen != 0 && m_str)
152       memcpy(res, m_str, byteLen);
153     return res;
154     */
155   }
156 
157   /*
158   void Attach(BSTR src) { m_str = src; }
159   BSTR Detach()
160   {
161     BSTR s = m_str;
162     m_str = NULL;
163     return s;
164   }
165   */
166 
Empty()167   void Empty()
168   {
169     ::SysFreeString(m_str);
170     m_str = NULL;
171   }
172 };
173 
174 
175 class CMyComBSTR_Wipe: public CMyComBSTR
176 {
Z7_CLASS_NO_COPY(CMyComBSTR_Wipe)177   Z7_CLASS_NO_COPY(CMyComBSTR_Wipe)
178 public:
179   CMyComBSTR_Wipe(): CMyComBSTR() {}
~CMyComBSTR_Wipe()180   ~CMyComBSTR_Wipe() { Wipe_and_Free(); }
181 };
182 
183 
184 
185 /*
186   If CMyUnknownImp doesn't use virtual destructor, the code size is smaller.
187   But if some class_1 derived from CMyUnknownImp
188     uses Z7_COM_ADDREF_RELEASE and IUnknown::Release()
189     and some another class_2 is derived from class_1,
190     then class_1 must use virtual destructor:
191       virtual ~class_1();
192     In that case, class_1::Release() calls correct destructor of class_2.
193   We can use virtual ~CMyUnknownImp() to disable warning
194     "class has virtual functions, but destructor is not virtual".
195   Also we can use virtual ~IUnknown() {} in MyWindows.h
196 */
197 
198 class CMyUnknownImp
199 {
Z7_CLASS_NO_COPY(CMyUnknownImp)200   Z7_CLASS_NO_COPY(CMyUnknownImp)
201 protected:
202   ULONG _m_RefCount;
203   CMyUnknownImp(): _m_RefCount(0) {}
204 
205   #ifdef _WIN32
206   #if defined(__GNUC__) || defined(__clang__)
207   // virtual ~CMyUnknownImp() {} // to disable GCC/CLANG varnings
208   #endif
209   #endif
210 };
211 
212 
213 
214 #define Z7_COM_QI_BEGIN \
215   private: STDMETHOD(QueryInterface) (REFGUID iid, void **outObject) throw() Z7_override Z7_final \
216     { *outObject = NULL;
217 
218 #define Z7_COM_QI_ENTRY(i) \
219   else if (iid == IID_ ## i) \
220     { i *ti = this;  *outObject = ti; }
221 //   { *outObject = (void *)(i *)this; }
222 
223 #define Z7_COM_QI_ENTRY_UNKNOWN_0 \
224   if (iid == IID_IUnknown) \
225     { IUnknown *tu = this;  *outObject = tu; }
226 
227 #define Z7_COM_QI_ENTRY_UNKNOWN(i) \
228   if (iid == IID_IUnknown) \
229     { i *ti = this;  IUnknown *tu = ti;  *outObject = tu; }
230 //    { *outObject = (void *)(IUnknown *)(i *)this; }
231 
232 #define Z7_COM_QI_BEGIN2(i) \
233   Z7_COM_QI_BEGIN \
234   Z7_COM_QI_ENTRY_UNKNOWN(i) \
235   Z7_COM_QI_ENTRY(i)
236 
237 #define Z7_COM_QI_END \
238   else return E_NOINTERFACE; \
239   ++_m_RefCount; /* AddRef(); */ return S_OK; }
240 
241 #define Z7_COM_ADDREF_RELEASE \
242   private: \
243   STDMETHOD_(ULONG, AddRef)() throw() Z7_override Z7_final \
244     { return ++_m_RefCount; } \
245   STDMETHOD_(ULONG, Release)() throw() Z7_override Z7_final \
246     { if (--_m_RefCount != 0) return _m_RefCount;  delete this;  return 0; } \
247 
248 #define Z7_COM_UNKNOWN_IMP_SPEC(i) \
249   Z7_COM_QI_BEGIN \
250   i \
251   Z7_COM_QI_END \
252   Z7_COM_ADDREF_RELEASE
253 
254 
255 #define Z7_COM_UNKNOWN_IMP_0 \
256   Z7_COM_QI_BEGIN \
257   Z7_COM_QI_ENTRY_UNKNOWN_0 \
258   Z7_COM_QI_END \
259   Z7_COM_ADDREF_RELEASE
260 
261 #define Z7_COM_UNKNOWN_IMP_1(i) \
262   Z7_COM_UNKNOWN_IMP_SPEC( \
263   Z7_COM_QI_ENTRY_UNKNOWN(i) \
264   Z7_COM_QI_ENTRY(i) \
265   )
266 
267 #define Z7_COM_UNKNOWN_IMP_2(i1, i2) \
268   Z7_COM_UNKNOWN_IMP_SPEC( \
269   Z7_COM_QI_ENTRY_UNKNOWN(i1) \
270   Z7_COM_QI_ENTRY(i1) \
271   Z7_COM_QI_ENTRY(i2) \
272   )
273 
274 #define Z7_COM_UNKNOWN_IMP_3(i1, i2, i3) \
275   Z7_COM_UNKNOWN_IMP_SPEC( \
276   Z7_COM_QI_ENTRY_UNKNOWN(i1) \
277   Z7_COM_QI_ENTRY(i1) \
278   Z7_COM_QI_ENTRY(i2) \
279   Z7_COM_QI_ENTRY(i3) \
280   )
281 
282 #define Z7_COM_UNKNOWN_IMP_4(i1, i2, i3, i4) \
283   Z7_COM_UNKNOWN_IMP_SPEC( \
284   Z7_COM_QI_ENTRY_UNKNOWN(i1) \
285   Z7_COM_QI_ENTRY(i1) \
286   Z7_COM_QI_ENTRY(i2) \
287   Z7_COM_QI_ENTRY(i3) \
288   Z7_COM_QI_ENTRY(i4) \
289   )
290 
291 #define Z7_COM_UNKNOWN_IMP_5(i1, i2, i3, i4, i5) \
292   Z7_COM_UNKNOWN_IMP_SPEC( \
293   Z7_COM_QI_ENTRY_UNKNOWN(i1) \
294   Z7_COM_QI_ENTRY(i1) \
295   Z7_COM_QI_ENTRY(i2) \
296   Z7_COM_QI_ENTRY(i3) \
297   Z7_COM_QI_ENTRY(i4) \
298   Z7_COM_QI_ENTRY(i5) \
299   )
300 
301 #define Z7_COM_UNKNOWN_IMP_6(i1, i2, i3, i4, i5, i6) \
302   Z7_COM_UNKNOWN_IMP_SPEC( \
303   Z7_COM_QI_ENTRY_UNKNOWN(i1) \
304   Z7_COM_QI_ENTRY(i1) \
305   Z7_COM_QI_ENTRY(i2) \
306   Z7_COM_QI_ENTRY(i3) \
307   Z7_COM_QI_ENTRY(i4) \
308   Z7_COM_QI_ENTRY(i5) \
309   Z7_COM_QI_ENTRY(i6) \
310   )
311 
312 #define Z7_COM_UNKNOWN_IMP_7(i1, i2, i3, i4, i5, i6, i7) \
313   Z7_COM_UNKNOWN_IMP_SPEC( \
314   Z7_COM_QI_ENTRY_UNKNOWN(i1) \
315   Z7_COM_QI_ENTRY(i1) \
316   Z7_COM_QI_ENTRY(i2) \
317   Z7_COM_QI_ENTRY(i3) \
318   Z7_COM_QI_ENTRY(i4) \
319   Z7_COM_QI_ENTRY(i5) \
320   Z7_COM_QI_ENTRY(i6) \
321   Z7_COM_QI_ENTRY(i7) \
322   )
323 
324 
325 #define Z7_IFACES_IMP_UNK_1(i1) \
326   Z7_COM_UNKNOWN_IMP_1(i1) \
327   Z7_IFACE_COM7_IMP(i1) \
328 
329 #define Z7_IFACES_IMP_UNK_2(i1, i2) \
330   Z7_COM_UNKNOWN_IMP_2(i1, i2) \
331   Z7_IFACE_COM7_IMP(i1) \
332   Z7_IFACE_COM7_IMP(i2) \
333 
334 #define Z7_IFACES_IMP_UNK_3(i1, i2, i3) \
335   Z7_COM_UNKNOWN_IMP_3(i1, i2, i3) \
336   Z7_IFACE_COM7_IMP(i1) \
337   Z7_IFACE_COM7_IMP(i2) \
338   Z7_IFACE_COM7_IMP(i3) \
339 
340 #define Z7_IFACES_IMP_UNK_4(i1, i2, i3, i4) \
341   Z7_COM_UNKNOWN_IMP_4(i1, i2, i3, i4) \
342   Z7_IFACE_COM7_IMP(i1) \
343   Z7_IFACE_COM7_IMP(i2) \
344   Z7_IFACE_COM7_IMP(i3) \
345   Z7_IFACE_COM7_IMP(i4) \
346 
347 #define Z7_IFACES_IMP_UNK_5(i1, i2, i3, i4, i5) \
348   Z7_COM_UNKNOWN_IMP_5(i1, i2, i3, i4, i5) \
349   Z7_IFACE_COM7_IMP(i1) \
350   Z7_IFACE_COM7_IMP(i2) \
351   Z7_IFACE_COM7_IMP(i3) \
352   Z7_IFACE_COM7_IMP(i4) \
353   Z7_IFACE_COM7_IMP(i5) \
354 
355 #define Z7_IFACES_IMP_UNK_6(i1, i2, i3, i4, i5, i6) \
356   Z7_COM_UNKNOWN_IMP_6(i1, i2, i3, i4, i5, i6) \
357   Z7_IFACE_COM7_IMP(i1) \
358   Z7_IFACE_COM7_IMP(i2) \
359   Z7_IFACE_COM7_IMP(i3) \
360   Z7_IFACE_COM7_IMP(i4) \
361   Z7_IFACE_COM7_IMP(i5) \
362   Z7_IFACE_COM7_IMP(i6) \
363 
364 
365 #define Z7_CLASS_IMP_COM_0(c) \
366   Z7_class_final(c) : \
367   public IUnknown, \
368   public CMyUnknownImp { \
369   Z7_COM_UNKNOWN_IMP_0 \
370   private:
371 
372 #define Z7_CLASS_IMP_COM_1(c, i1) \
373   Z7_class_final(c) : \
374   public i1, \
375   public CMyUnknownImp { \
376   Z7_IFACES_IMP_UNK_1(i1) \
377   private:
378 
379 #define Z7_CLASS_IMP_COM_2(c, i1, i2) \
380   Z7_class_final(c) : \
381   public i1, \
382   public i2, \
383   public CMyUnknownImp { \
384   Z7_IFACES_IMP_UNK_2(i1, i2) \
385   private:
386 
387 #define Z7_CLASS_IMP_COM_3(c, i1, i2, i3) \
388   Z7_class_final(c) : \
389   public i1, \
390   public i2, \
391   public i3, \
392   public CMyUnknownImp { \
393   Z7_IFACES_IMP_UNK_3(i1, i2, i3) \
394   private:
395 
396 #define Z7_CLASS_IMP_COM_4(c, i1, i2, i3, i4) \
397   Z7_class_final(c) : \
398   public i1, \
399   public i2, \
400   public i3, \
401   public i4, \
402   public CMyUnknownImp { \
403   Z7_IFACES_IMP_UNK_4(i1, i2, i3, i4) \
404   private:
405 
406 #define Z7_CLASS_IMP_COM_5(c, i1, i2, i3, i4, i5) \
407   Z7_class_final(c) : \
408   public i1, \
409   public i2, \
410   public i3, \
411   public i4, \
412   public i5, \
413   public CMyUnknownImp { \
414   Z7_IFACES_IMP_UNK_5(i1, i2, i3, i4, i5) \
415   private:
416 
417 #define Z7_CLASS_IMP_COM_6(c, i1, i2, i3, i4, i5, i6) \
418   Z7_class_final(c) : \
419   public i1, \
420   public i2, \
421   public i3, \
422   public i4, \
423   public i5, \
424   public i6, \
425   public CMyUnknownImp { \
426   Z7_IFACES_IMP_UNK_6(i1, i2, i3, i4, i5, i6) \
427   private:
428 
429 
430 /*
431 #define Z7_CLASS_IMP_NOQIB_0(c) \
432   Z7_class_final(c) : \
433   public IUnknown, \
434   public CMyUnknownImp { \
435   Z7_COM_UNKNOWN_IMP_0 \
436   private:
437 */
438 
439 #define Z7_CLASS_IMP_NOQIB_1(c, i1) \
440   Z7_class_final(c) : \
441   public i1, \
442   public CMyUnknownImp { \
443   Z7_COM_UNKNOWN_IMP_0 \
444   Z7_IFACE_COM7_IMP(i1) \
445   private:
446 
447 #define Z7_CLASS_IMP_NOQIB_2(c, i1, i2) \
448   Z7_class_final(c) : \
449   public i1, \
450   public i2, \
451   public CMyUnknownImp { \
452   Z7_COM_UNKNOWN_IMP_1(i2) \
453   Z7_IFACE_COM7_IMP(i1) \
454   Z7_IFACE_COM7_IMP(i2) \
455   private:
456 
457 #define Z7_CLASS_IMP_NOQIB_3(c, i1, i2, i3) \
458   Z7_class_final(c) : \
459   public i1, \
460   public i2, \
461   public i3, \
462   public CMyUnknownImp { \
463   Z7_COM_UNKNOWN_IMP_2(i2, i3) \
464   Z7_IFACE_COM7_IMP(i1) \
465   Z7_IFACE_COM7_IMP(i2) \
466   Z7_IFACE_COM7_IMP(i3) \
467   private:
468 
469 #define Z7_CLASS_IMP_NOQIB_4(c, i1, i2, i3, i4) \
470   Z7_class_final(c) : \
471   public i1, \
472   public i2, \
473   public i3, \
474   public i4, \
475   public CMyUnknownImp { \
476   Z7_COM_UNKNOWN_IMP_3(i2, i3, i4) \
477   Z7_IFACE_COM7_IMP(i1) \
478   Z7_IFACE_COM7_IMP(i2) \
479   Z7_IFACE_COM7_IMP(i3) \
480   Z7_IFACE_COM7_IMP(i4) \
481 
482 /*
483 #define Z7_CLASS_IMP_NOQIB_5(c, i1, i2, i3, i4, i5) \
484   Z7_class_final(c) : \
485   public i1, \
486   public i2, \
487   public i3, \
488   public i4, \
489   public i5, \
490   public CMyUnknownImp { \
491   Z7_COM_UNKNOWN_IMP_4(i2, i3, i4, i5) \
492   Z7_IFACE_COM7_IMP(i1) \
493   Z7_IFACE_COM7_IMP(i2) \
494   Z7_IFACE_COM7_IMP(i3) \
495   Z7_IFACE_COM7_IMP(i4) \
496   Z7_IFACE_COM7_IMP(i5) \
497 */
498 
499 
500 #define Z7_CLASS_IMP_IInStream(c) \
501   class c Z7_final : \
502   public IInStream, \
503   public CMyUnknownImp { \
504   Z7_IFACES_IMP_UNK_2(ISequentialInStream, IInStream) \
505 
506 
507 #define k_My_HRESULT_WritingWasCut 0x20000010
508 
509 #endif
510