• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // MyCom.h
2 
3 #ifndef __MY_COM_H
4 #define __MY_COM_H
5 
6 #include "MyWindows.h"
7 #include "MyTypes.h"
8 
9 #ifndef RINOK
10 #define RINOK(x) { HRESULT __result_ = (x); if (__result_ != S_OK) return __result_; }
11 #endif
12 
13 template <class T>
14 class CMyComPtr
15 {
16   T* _p;
17 public:
CMyComPtr()18   CMyComPtr(): _p(NULL) {}
throw()19   CMyComPtr(T* p) throw() { if ((_p = p) != NULL) p->AddRef(); }
throw()20   CMyComPtr(const CMyComPtr<T>& lp) throw() { if ((_p = lp._p) != NULL) _p->AddRef(); }
~CMyComPtr()21   ~CMyComPtr() { if (_p) _p->Release(); }
Release()22   void Release() { if (_p) { _p->Release(); _p = NULL; } }
23   operator T*() const {  return (T*)_p;  }
24   // T& operator*() const {  return *_p; }
25   T** operator&() { return &_p; }
26   T* operator->() const { return _p; }
27   T* operator=(T* p)
28   {
29     if (p)
30       p->AddRef();
31     if (_p)
32       _p->Release();
33     _p = p;
34     return p;
35   }
36   T* operator=(const CMyComPtr<T>& lp) { return (*this = lp._p); }
37   bool operator!() const { return (_p == NULL); }
38   // bool operator==(T* pT) const {  return _p == pT; }
Attach(T * p2)39   void Attach(T* p2)
40   {
41     Release();
42     _p = p2;
43   }
Detach()44   T* Detach()
45   {
46     T* pt = _p;
47     _p = NULL;
48     return pt;
49   }
50   #ifdef _WIN32
51   HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
52   {
53     return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p);
54   }
55   #endif
56   /*
57   HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
58   {
59     CLSID clsid;
60     HRESULT hr = CLSIDFromProgID(szProgID, &clsid);
61     ATLASSERT(_p == NULL);
62     if (SUCCEEDED(hr))
63       hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p);
64     return hr;
65   }
66   */
67   template <class Q>
QueryInterface(REFGUID iid,Q ** pp)68   HRESULT QueryInterface(REFGUID iid, Q** pp) const throw()
69   {
70     // if (*pp) throw 20220216; // for debug
71     return _p->QueryInterface(iid, (void**)pp);
72   }
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;
CLASS_NO_COPY(CMyComBSTR)86   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 {
CLASS_NO_COPY(CMyComBSTR_Wipe)177   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 MY_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 
194   We use virtual ~CMyUnknownImp() to disable warning
195     "class has virtual functions, but destructor is not virtual".
196 
197   also we can use virtual ~IUnknown() {} in MyWindows.h
198 */
199 
200 class CMyUnknownImp
201 {
CLASS_NO_COPY(CMyUnknownImp)202   CLASS_NO_COPY(CMyUnknownImp)
203 public:
204   ULONG __m_RefCount;
205   CMyUnknownImp(): __m_RefCount(0) {}
206 
207   #ifdef _WIN32
208   #if defined(__GNUC__) || defined(__clang__)
209   virtual // to disable GCC/CLANG varnings
210   #endif
211   #endif
~CMyUnknownImp()212   ~CMyUnknownImp() {}
213 };
214 
215 
216 
217 #define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \
218 (REFGUID iid, void **outObject) throw() { *outObject = NULL;
219 
220 #define MY_QUERYINTERFACE_ENTRY(i) else if (iid == IID_ ## i) \
221     { *outObject = (void *)(i *)this; }
222 
223 #define MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) if (iid == IID_IUnknown) \
224     { *outObject = (void *)(IUnknown *)(i *)this; }
225 
226 #define MY_QUERYINTERFACE_BEGIN2(i) MY_QUERYINTERFACE_BEGIN \
227     MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \
228     MY_QUERYINTERFACE_ENTRY(i)
229 
230 #define MY_QUERYINTERFACE_END else return E_NOINTERFACE; ++__m_RefCount; /* AddRef(); */ return S_OK; }
231 
232 #define MY_ADDREF_RELEASE \
233 STDMETHOD_(ULONG, AddRef)() throw() { return ++__m_RefCount; } \
234 STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) return __m_RefCount; \
235     delete this; return 0; }
236 
237 #define MY_UNKNOWN_IMP_SPEC(i) \
238   MY_QUERYINTERFACE_BEGIN \
239   i \
240   MY_QUERYINTERFACE_END \
241   MY_ADDREF_RELEASE
242 
243 
244 #define MY_UNKNOWN_IMP MY_QUERYINTERFACE_BEGIN \
245   MY_QUERYINTERFACE_ENTRY_UNKNOWN(IUnknown) \
246   MY_QUERYINTERFACE_END \
247   MY_ADDREF_RELEASE
248 
249 #define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \
250   MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \
251   MY_QUERYINTERFACE_ENTRY(i) \
252   )
253 
254 #define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \
255   MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
256   MY_QUERYINTERFACE_ENTRY(i1) \
257   MY_QUERYINTERFACE_ENTRY(i2) \
258   )
259 
260 #define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \
261   MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
262   MY_QUERYINTERFACE_ENTRY(i1) \
263   MY_QUERYINTERFACE_ENTRY(i2) \
264   MY_QUERYINTERFACE_ENTRY(i3) \
265   )
266 
267 #define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \
268   MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
269   MY_QUERYINTERFACE_ENTRY(i1) \
270   MY_QUERYINTERFACE_ENTRY(i2) \
271   MY_QUERYINTERFACE_ENTRY(i3) \
272   MY_QUERYINTERFACE_ENTRY(i4) \
273   )
274 
275 #define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \
276   MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
277   MY_QUERYINTERFACE_ENTRY(i1) \
278   MY_QUERYINTERFACE_ENTRY(i2) \
279   MY_QUERYINTERFACE_ENTRY(i3) \
280   MY_QUERYINTERFACE_ENTRY(i4) \
281   MY_QUERYINTERFACE_ENTRY(i5) \
282   )
283 
284 #define MY_UNKNOWN_IMP6(i1, i2, i3, i4, i5, i6) MY_UNKNOWN_IMP_SPEC( \
285   MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
286   MY_QUERYINTERFACE_ENTRY(i1) \
287   MY_QUERYINTERFACE_ENTRY(i2) \
288   MY_QUERYINTERFACE_ENTRY(i3) \
289   MY_QUERYINTERFACE_ENTRY(i4) \
290   MY_QUERYINTERFACE_ENTRY(i5) \
291   MY_QUERYINTERFACE_ENTRY(i6) \
292   )
293 
294 #define MY_UNKNOWN_IMP7(i1, i2, i3, i4, i5, i6, i7) MY_UNKNOWN_IMP_SPEC( \
295   MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
296   MY_QUERYINTERFACE_ENTRY(i1) \
297   MY_QUERYINTERFACE_ENTRY(i2) \
298   MY_QUERYINTERFACE_ENTRY(i3) \
299   MY_QUERYINTERFACE_ENTRY(i4) \
300   MY_QUERYINTERFACE_ENTRY(i5) \
301   MY_QUERYINTERFACE_ENTRY(i6) \
302   MY_QUERYINTERFACE_ENTRY(i7) \
303   )
304 
305 const HRESULT k_My_HRESULT_WritingWasCut = 0x20000010;
306 
307 #endif
308