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     return _p->QueryInterface(iid, (void**)pp);
71   }
72 };
73 
74 //////////////////////////////////////////////////////////
75 
StringToBstr(LPCOLESTR src,BSTR * bstr)76 inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr)
77 {
78   *bstr = ::SysAllocString(src);
79   return (*bstr) ? S_OK : E_OUTOFMEMORY;
80 }
81 
82 class CMyComBSTR
83 {
84   BSTR m_str;
CLASS_NO_COPY(CMyComBSTR)85   CLASS_NO_COPY(CMyComBSTR)
86 public:
87   CMyComBSTR(): m_str(NULL) {}
~CMyComBSTR()88   ~CMyComBSTR() { ::SysFreeString(m_str); }
89   BSTR* operator&() { return &m_str; }
LPCOLESTR()90   operator LPCOLESTR() const { return m_str; }
91   // operator bool() const { return m_str != NULL; }
92   // bool operator!() const { return m_str == NULL; }
93 
Wipe_and_Free()94   void Wipe_and_Free()
95   {
96     if (m_str)
97     {
98       memset(m_str, 0, ::SysStringLen(m_str) * sizeof(*m_str));
99       Empty();
100     }
101   }
102 
103 private:
104   // operator BSTR() const { return m_str; }
105 
CMyComBSTR(LPCOLESTR src)106   CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); }
107   // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); }
108   // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize);  }
109   // CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); }
110 
111   /*
112   CMyComBSTR(REFGUID src)
113   {
114     LPOLESTR szGuid;
115     StringFromCLSID(src, &szGuid);
116     m_str = ::SysAllocString(szGuid);
117     CoTaskMemFree(szGuid);
118   }
119   */
120 
121   /*
122   CMyComBSTR& operator=(const CMyComBSTR& src)
123   {
124     if (m_str != src.m_str)
125     {
126       if (m_str)
127         ::SysFreeString(m_str);
128       m_str = src.MyCopy();
129     }
130     return *this;
131   }
132   */
133 
134   CMyComBSTR& operator=(LPCOLESTR src)
135   {
136     ::SysFreeString(m_str);
137     m_str = ::SysAllocString(src);
138     return *this;
139   }
140 
Len()141   unsigned Len() const { return ::SysStringLen(m_str); }
142 
MyCopy()143   BSTR MyCopy() const
144   {
145     // We don't support Byte BSTRs here
146     return ::SysAllocStringLen(m_str, ::SysStringLen(m_str));
147     /*
148     UINT byteLen = ::SysStringByteLen(m_str);
149     BSTR res = ::SysAllocStringByteLen(NULL, byteLen);
150     if (res && byteLen != 0 && m_str)
151       memcpy(res, m_str, byteLen);
152     return res;
153     */
154   }
155 
156   /*
157   void Attach(BSTR src) { m_str = src; }
158   BSTR Detach()
159   {
160     BSTR s = m_str;
161     m_str = NULL;
162     return s;
163   }
164   */
165 
Empty()166   void Empty()
167   {
168     ::SysFreeString(m_str);
169     m_str = NULL;
170   }
171 };
172 
173 
174 class CMyComBSTR_Wipe: public CMyComBSTR
175 {
CLASS_NO_COPY(CMyComBSTR_Wipe)176   CLASS_NO_COPY(CMyComBSTR_Wipe)
177 public:
178   CMyComBSTR_Wipe(): CMyComBSTR() {}
~CMyComBSTR_Wipe()179   ~CMyComBSTR_Wipe() { Wipe_and_Free(); }
180 };
181 
182 
183 
184 /*
185   If CMyUnknownImp doesn't use virtual destructor, the code size is smaller.
186   But if some class_1 derived from CMyUnknownImp
187     uses MY_ADDREF_RELEASE and IUnknown::Release()
188     and some another class_2 is derived from class_1,
189     then class_1 must use virtual destructor:
190       virtual ~class_1();
191     In that case, class_1::Release() calls correct destructor of class_2.
192 
193   We use virtual ~CMyUnknownImp() to disable warning
194     "class has virtual functions, but destructor is not virtual".
195 
196   also we can use virtual ~IUnknown() {} in MyWindows.h
197 */
198 
199 class CMyUnknownImp
200 {
CLASS_NO_COPY(CMyUnknownImp)201   CLASS_NO_COPY(CMyUnknownImp)
202 public:
203   ULONG __m_RefCount;
204   CMyUnknownImp(): __m_RefCount(0) {}
205 
206   #ifdef _WIN32
207   #if defined(__GNUC__) || defined(__clang__)
208   virtual // to disable GCC/CLANG varnings
209   #endif
210   #endif
~CMyUnknownImp()211   ~CMyUnknownImp() {}
212 };
213 
214 
215 
216 #define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \
217 (REFGUID iid, void **outObject) throw() { *outObject = NULL;
218 
219 #define MY_QUERYINTERFACE_ENTRY(i) else if (iid == IID_ ## i) \
220     { *outObject = (void *)(i *)this; }
221 
222 #define MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) if (iid == IID_IUnknown) \
223     { *outObject = (void *)(IUnknown *)(i *)this; }
224 
225 #define MY_QUERYINTERFACE_BEGIN2(i) MY_QUERYINTERFACE_BEGIN \
226     MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \
227     MY_QUERYINTERFACE_ENTRY(i)
228 
229 #define MY_QUERYINTERFACE_END else return E_NOINTERFACE; ++__m_RefCount; /* AddRef(); */ return S_OK; }
230 
231 #define MY_ADDREF_RELEASE \
232 STDMETHOD_(ULONG, AddRef)() throw() { return ++__m_RefCount; } \
233 STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) return __m_RefCount; \
234     delete this; return 0; }
235 
236 #define MY_UNKNOWN_IMP_SPEC(i) \
237   MY_QUERYINTERFACE_BEGIN \
238   i \
239   MY_QUERYINTERFACE_END \
240   MY_ADDREF_RELEASE
241 
242 
243 #define MY_UNKNOWN_IMP MY_QUERYINTERFACE_BEGIN \
244   MY_QUERYINTERFACE_ENTRY_UNKNOWN(IUnknown) \
245   MY_QUERYINTERFACE_END \
246   MY_ADDREF_RELEASE
247 
248 #define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \
249   MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \
250   MY_QUERYINTERFACE_ENTRY(i) \
251   )
252 
253 #define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \
254   MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
255   MY_QUERYINTERFACE_ENTRY(i1) \
256   MY_QUERYINTERFACE_ENTRY(i2) \
257   )
258 
259 #define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \
260   MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
261   MY_QUERYINTERFACE_ENTRY(i1) \
262   MY_QUERYINTERFACE_ENTRY(i2) \
263   MY_QUERYINTERFACE_ENTRY(i3) \
264   )
265 
266 #define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \
267   MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
268   MY_QUERYINTERFACE_ENTRY(i1) \
269   MY_QUERYINTERFACE_ENTRY(i2) \
270   MY_QUERYINTERFACE_ENTRY(i3) \
271   MY_QUERYINTERFACE_ENTRY(i4) \
272   )
273 
274 #define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \
275   MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
276   MY_QUERYINTERFACE_ENTRY(i1) \
277   MY_QUERYINTERFACE_ENTRY(i2) \
278   MY_QUERYINTERFACE_ENTRY(i3) \
279   MY_QUERYINTERFACE_ENTRY(i4) \
280   MY_QUERYINTERFACE_ENTRY(i5) \
281   )
282 
283 #define MY_UNKNOWN_IMP6(i1, i2, i3, i4, i5, i6) MY_UNKNOWN_IMP_SPEC( \
284   MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
285   MY_QUERYINTERFACE_ENTRY(i1) \
286   MY_QUERYINTERFACE_ENTRY(i2) \
287   MY_QUERYINTERFACE_ENTRY(i3) \
288   MY_QUERYINTERFACE_ENTRY(i4) \
289   MY_QUERYINTERFACE_ENTRY(i5) \
290   MY_QUERYINTERFACE_ENTRY(i6) \
291   )
292 
293 #define MY_UNKNOWN_IMP7(i1, i2, i3, i4, i5, i6, i7) MY_UNKNOWN_IMP_SPEC( \
294   MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
295   MY_QUERYINTERFACE_ENTRY(i1) \
296   MY_QUERYINTERFACE_ENTRY(i2) \
297   MY_QUERYINTERFACE_ENTRY(i3) \
298   MY_QUERYINTERFACE_ENTRY(i4) \
299   MY_QUERYINTERFACE_ENTRY(i5) \
300   MY_QUERYINTERFACE_ENTRY(i6) \
301   MY_QUERYINTERFACE_ENTRY(i7) \
302   )
303 
304 const HRESULT k_My_HRESULT_WritingWasCut = 0x20000010;
305 
306 #endif
307