1 // MyCom.h
2 
3 #ifndef __MY_COM_H
4 #define __MY_COM_H
5 
6 #include "MyWindows.h"
7 
8 #ifndef RINOK
9 #define RINOK(x) { HRESULT __result_ = (x); if (__result_ != S_OK) return __result_; }
10 #endif
11 
12 template <class T>
13 class CMyComPtr
14 {
15   T* _p;
16 public:
CMyComPtr()17   CMyComPtr(): _p(NULL) {}
throw()18   CMyComPtr(T* p) throw() { if ((_p = p) != NULL) p->AddRef(); }
throw()19   CMyComPtr(const CMyComPtr<T>& lp) throw() { if ((_p = lp._p) != NULL) _p->AddRef(); }
~CMyComPtr()20   ~CMyComPtr() { if (_p) _p->Release(); }
Release()21   void Release() { if (_p) { _p->Release(); _p = NULL; } }
22   operator T*() const {  return (T*)_p;  }
23   // T& operator*() const {  return *_p; }
24   T** operator&() { return &_p; }
25   T* operator->() const { return _p; }
26   T* operator=(T* p)
27   {
28     if (p)
29       p->AddRef();
30     if (_p)
31       _p->Release();
32     _p = p;
33     return p;
34   }
35   T* operator=(const CMyComPtr<T>& lp) { return (*this = lp._p); }
36   bool operator!() const { return (_p == NULL); }
37   // bool operator==(T* pT) const {  return _p == pT; }
Attach(T * p2)38   void Attach(T* p2)
39   {
40     Release();
41     _p = p2;
42   }
Detach()43   T* Detach()
44   {
45     T* pt = _p;
46     _p = NULL;
47     return pt;
48   }
49   #ifdef _WIN32
50   HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
51   {
52     return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p);
53   }
54   #endif
55   /*
56   HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
57   {
58     CLSID clsid;
59     HRESULT hr = CLSIDFromProgID(szProgID, &clsid);
60     ATLASSERT(_p == NULL);
61     if (SUCCEEDED(hr))
62       hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p);
63     return hr;
64   }
65   */
66   template <class Q>
QueryInterface(REFGUID iid,Q ** pp)67   HRESULT QueryInterface(REFGUID iid, Q** pp) const throw()
68   {
69     return _p->QueryInterface(iid, (void**)pp);
70   }
71 };
72 
73 //////////////////////////////////////////////////////////
74 
StringToBstr(LPCOLESTR src,BSTR * bstr)75 inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr)
76 {
77   *bstr = ::SysAllocString(src);
78   return (*bstr) ? S_OK : E_OUTOFMEMORY;
79 }
80 
81 class CMyComBSTR
82 {
83   BSTR m_str;
84 
85 public:
CMyComBSTR()86   CMyComBSTR(): m_str(NULL) {}
~CMyComBSTR()87   ~CMyComBSTR() { ::SysFreeString(m_str); }
88   BSTR* operator&() { return &m_str; }
LPCOLESTR()89   operator LPCOLESTR() const { return m_str; }
90   // operator bool() const { return m_str != NULL; }
91   // bool operator!() const { return m_str == NULL; }
92 private:
93   // operator BSTR() const { return m_str; }
94 
CMyComBSTR(LPCOLESTR src)95   CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); }
96   // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); }
97   // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize);  }
CMyComBSTR(const CMyComBSTR & src)98   CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); }
99 
100   /*
101   CMyComBSTR(REFGUID src)
102   {
103     LPOLESTR szGuid;
104     StringFromCLSID(src, &szGuid);
105     m_str = ::SysAllocString(szGuid);
106     CoTaskMemFree(szGuid);
107   }
108   */
109 
110   CMyComBSTR& operator=(const CMyComBSTR& src)
111   {
112     if (m_str != src.m_str)
113     {
114       if (m_str)
115         ::SysFreeString(m_str);
116       m_str = src.MyCopy();
117     }
118     return *this;
119   }
120 
121   CMyComBSTR& operator=(LPCOLESTR src)
122   {
123     ::SysFreeString(m_str);
124     m_str = ::SysAllocString(src);
125     return *this;
126   }
127 
Len()128   unsigned Len() const { return ::SysStringLen(m_str); }
129 
MyCopy()130   BSTR MyCopy() const
131   {
132     // We don't support Byte BSTRs here
133     return ::SysAllocStringLen(m_str, ::SysStringLen(m_str));
134     /*
135     UINT byteLen = ::SysStringByteLen(m_str);
136     BSTR res = ::SysAllocStringByteLen(NULL, byteLen);
137     if (res && byteLen != 0 && m_str)
138       memcpy(res, m_str, byteLen);
139     return res;
140     */
141   }
142 
143   /*
144   void Attach(BSTR src) { m_str = src; }
145   BSTR Detach()
146   {
147     BSTR s = m_str;
148     m_str = NULL;
149     return s;
150   }
151   */
152 
Empty()153   void Empty()
154   {
155     ::SysFreeString(m_str);
156     m_str = NULL;
157   }
158 };
159 
160 
161 
162 /*
163   If CMyUnknownImp doesn't use virtual destructor, the code size is smaller.
164   But if some class_1 derived from CMyUnknownImp
165     uses MY_ADDREF_RELEASE and IUnknown::Release()
166     and some another class_2 is derived from class_1,
167     then class_1 must use virtual destructor:
168       virtual ~class_1();
169     In that case, class_1::Release() calls correct destructor of class_2.
170 
171   Also you can use virtual ~CMyUnknownImp(), if you want to disable warning
172     "class has virtual functions, but destructor is not virtual".
173 */
174 
175 class CMyUnknownImp
176 {
177 public:
178   ULONG __m_RefCount;
CMyUnknownImp()179   CMyUnknownImp(): __m_RefCount(0) {}
180 
181   // virtual
~CMyUnknownImp()182   ~CMyUnknownImp() {}
183 };
184 
185 
186 
187 #define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \
188 (REFGUID iid, void **outObject) throw() { *outObject = NULL;
189 
190 #define MY_QUERYINTERFACE_ENTRY(i) else if (iid == IID_ ## i) \
191     { *outObject = (void *)(i *)this; }
192 
193 #define MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) if (iid == IID_IUnknown) \
194     { *outObject = (void *)(IUnknown *)(i *)this; }
195 
196 #define MY_QUERYINTERFACE_BEGIN2(i) MY_QUERYINTERFACE_BEGIN \
197     MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \
198     MY_QUERYINTERFACE_ENTRY(i)
199 
200 #define MY_QUERYINTERFACE_END else return E_NOINTERFACE; ++__m_RefCount; /* AddRef(); */ return S_OK; }
201 
202 #define MY_ADDREF_RELEASE \
203 STDMETHOD_(ULONG, AddRef)() throw() { return ++__m_RefCount; } \
204 STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0)  \
205   return __m_RefCount; delete this; return 0; }
206 
207 #define MY_UNKNOWN_IMP_SPEC(i) \
208   MY_QUERYINTERFACE_BEGIN \
209   i \
210   MY_QUERYINTERFACE_END \
211   MY_ADDREF_RELEASE
212 
213 
214 #define MY_UNKNOWN_IMP MY_QUERYINTERFACE_BEGIN \
215   MY_QUERYINTERFACE_ENTRY_UNKNOWN(IUnknown) \
216   MY_QUERYINTERFACE_END \
217   MY_ADDREF_RELEASE
218 
219 #define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \
220   MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \
221   MY_QUERYINTERFACE_ENTRY(i) \
222   )
223 
224 #define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \
225   MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
226   MY_QUERYINTERFACE_ENTRY(i1) \
227   MY_QUERYINTERFACE_ENTRY(i2) \
228   )
229 
230 #define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \
231   MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
232   MY_QUERYINTERFACE_ENTRY(i1) \
233   MY_QUERYINTERFACE_ENTRY(i2) \
234   MY_QUERYINTERFACE_ENTRY(i3) \
235   )
236 
237 #define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \
238   MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
239   MY_QUERYINTERFACE_ENTRY(i1) \
240   MY_QUERYINTERFACE_ENTRY(i2) \
241   MY_QUERYINTERFACE_ENTRY(i3) \
242   MY_QUERYINTERFACE_ENTRY(i4) \
243   )
244 
245 #define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \
246   MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
247   MY_QUERYINTERFACE_ENTRY(i1) \
248   MY_QUERYINTERFACE_ENTRY(i2) \
249   MY_QUERYINTERFACE_ENTRY(i3) \
250   MY_QUERYINTERFACE_ENTRY(i4) \
251   MY_QUERYINTERFACE_ENTRY(i5) \
252   )
253 
254 #define MY_UNKNOWN_IMP6(i1, i2, i3, i4, i5, i6) MY_UNKNOWN_IMP_SPEC( \
255   MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
256   MY_QUERYINTERFACE_ENTRY(i1) \
257   MY_QUERYINTERFACE_ENTRY(i2) \
258   MY_QUERYINTERFACE_ENTRY(i3) \
259   MY_QUERYINTERFACE_ENTRY(i4) \
260   MY_QUERYINTERFACE_ENTRY(i5) \
261   MY_QUERYINTERFACE_ENTRY(i6) \
262   )
263 
264 #define MY_UNKNOWN_IMP7(i1, i2, i3, i4, i5, i6, i7) MY_UNKNOWN_IMP_SPEC( \
265   MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
266   MY_QUERYINTERFACE_ENTRY(i1) \
267   MY_QUERYINTERFACE_ENTRY(i2) \
268   MY_QUERYINTERFACE_ENTRY(i3) \
269   MY_QUERYINTERFACE_ENTRY(i4) \
270   MY_QUERYINTERFACE_ENTRY(i5) \
271   MY_QUERYINTERFACE_ENTRY(i6) \
272   MY_QUERYINTERFACE_ENTRY(i7) \
273   )
274 
275 const HRESULT k_My_HRESULT_WritingWasCut = 0x20000010;
276 
277 #endif
278