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: 17 CMyComPtr(): _p(NULL) {} 18 CMyComPtr(T* p) throw() { if ((_p = p) != NULL) p->AddRef(); } 19 CMyComPtr(const CMyComPtr<T>& lp) throw() { if ((_p = lp._p) != NULL) _p->AddRef(); } 20 ~CMyComPtr() { if (_p) _p->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; } 38 void Attach(T* p2) 39 { 40 Release(); 41 _p = p2; 42 } 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> 67 HRESULT QueryInterface(REFGUID iid, Q** pp) const throw() 68 { 69 return _p->QueryInterface(iid, (void**)pp); 70 } 71 }; 72 73 ////////////////////////////////////////////////////////// 74 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: 86 CMyComBSTR(): m_str(NULL) {} 87 ~CMyComBSTR() { ::SysFreeString(m_str); } 88 BSTR* operator&() { return &m_str; } 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 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); } 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 128 unsigned Len() const { return ::SysStringLen(m_str); } 129 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 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; 179 CMyUnknownImp(): __m_RefCount(0) {} 180 181 // virtual 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