diff options
Diffstat (limited to 'CPP/Common/MyCom.h')
-rw-r--r-- | CPP/Common/MyCom.h | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/CPP/Common/MyCom.h b/CPP/Common/MyCom.h new file mode 100644 index 0000000..ce2f0dd --- /dev/null +++ b/CPP/Common/MyCom.h | |||
@@ -0,0 +1,306 @@ | |||
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: | ||
18 | CMyComPtr(): _p(NULL) {} | ||
19 | CMyComPtr(T* p) throw() { if ((_p = p) != NULL) p->AddRef(); } | ||
20 | CMyComPtr(const CMyComPtr<T>& lp) throw() { if ((_p = lp._p) != NULL) _p->AddRef(); } | ||
21 | ~CMyComPtr() { if (_p) _p->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; } | ||
39 | void Attach(T* p2) | ||
40 | { | ||
41 | Release(); | ||
42 | _p = p2; | ||
43 | } | ||
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> | ||
68 | HRESULT QueryInterface(REFGUID iid, Q** pp) const throw() | ||
69 | { | ||
70 | return _p->QueryInterface(iid, (void**)pp); | ||
71 | } | ||
72 | }; | ||
73 | |||
74 | ////////////////////////////////////////////////////////// | ||
75 | |||
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; | ||
85 | CLASS_NO_COPY(CMyComBSTR) | ||
86 | public: | ||
87 | CMyComBSTR(): m_str(NULL) {} | ||
88 | ~CMyComBSTR() { ::SysFreeString(m_str); } | ||
89 | BSTR* operator&() { return &m_str; } | ||
90 | operator LPCOLESTR() const { return m_str; } | ||
91 | // operator bool() const { return m_str != NULL; } | ||
92 | // bool operator!() const { return m_str == NULL; } | ||
93 | |||
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 | |||
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 | |||
141 | unsigned Len() const { return ::SysStringLen(m_str); } | ||
142 | |||
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 | |||
166 | void Empty() | ||
167 | { | ||
168 | ::SysFreeString(m_str); | ||
169 | m_str = NULL; | ||
170 | } | ||
171 | }; | ||
172 | |||
173 | |||
174 | class CMyComBSTR_Wipe: public CMyComBSTR | ||
175 | { | ||
176 | CLASS_NO_COPY(CMyComBSTR_Wipe) | ||
177 | public: | ||
178 | CMyComBSTR_Wipe(): CMyComBSTR() {} | ||
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 | { | ||
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 | ||
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 | ||