1// MyCom.h 2 3#ifndef ZIP7_INC_MY_COM_H 4#define ZIP7_INC_MY_COM_H 5 6#include "MyWindows.h" 7#include "MyTypes.h" 8 9template <class T> 10class CMyComPtr 11{ 12 T* _p; 13public: 14 CMyComPtr(): _p(NULL) {} 15 CMyComPtr(T* p) throw() { if ((_p = p) != NULL) p->AddRef(); } 16 CMyComPtr(const CMyComPtr<T>& lp) throw() { if ((_p = lp._p) != NULL) _p->AddRef(); } 17 ~CMyComPtr() { if (_p) _p->Release(); } 18 void Release() { if (_p) { _p->Release(); _p = NULL; } } 19 operator T*() const { return (T*)_p; } 20 // T& operator*() const { return *_p; } 21 T** operator&() { return &_p; } 22 T* operator->() const { return _p; } 23 T* operator=(T* p) 24 { 25 if (p) 26 p->AddRef(); 27 if (_p) 28 _p->Release(); 29 _p = p; 30 return p; 31 } 32 T* operator=(const CMyComPtr<T>& lp) { return (*this = lp._p); } 33 bool operator!() const { return (_p == NULL); } 34 // bool operator==(T* pT) const { return _p == pT; } 35 void Attach(T* p2) 36 { 37 Release(); 38 _p = p2; 39 } 40 T* Detach() 41 { 42 T* pt = _p; 43 _p = NULL; 44 return pt; 45 } 46 #ifdef _WIN32 47 HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) 48 { 49 return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p); 50 } 51 #endif 52 /* 53 HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) 54 { 55 CLSID clsid; 56 HRESULT hr = CLSIDFromProgID(szProgID, &clsid); 57 ATLASSERT(_p == NULL); 58 if (SUCCEEDED(hr)) 59 hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p); 60 return hr; 61 } 62 */ 63 template <class Q> 64 HRESULT QueryInterface(REFGUID iid, Q** pp) const throw() 65 { 66 // if (*pp) throw 20220216; // for debug 67 return _p->QueryInterface(iid, (void**)pp); 68 } 69}; 70 71#define Z7_DECL_CMyComPtr_QI_FROM(i, v, unk) \ 72 CMyComPtr<i> v; (unk)->QueryInterface(IID_ ## i, (void **)&v); 73 74 75////////////////////////////////////////////////////////// 76 77inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr) 78{ 79 *bstr = ::SysAllocString(src); 80 return (*bstr) ? S_OK : E_OUTOFMEMORY; 81} 82 83class CMyComBSTR 84{ 85 BSTR m_str; 86 Z7_CLASS_NO_COPY(CMyComBSTR) 87public: 88 CMyComBSTR(): m_str(NULL) {} 89 ~CMyComBSTR() { ::SysFreeString(m_str); } 90 BSTR* operator&() { return &m_str; } 91 operator LPCOLESTR() const { return m_str; } 92 // operator bool() const { return m_str != NULL; } 93 // bool operator!() const { return m_str == NULL; } 94 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 104private: 105 // operator BSTR() const { return m_str; } 106 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 142 unsigned Len() const { return ::SysStringLen(m_str); } 143 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 167 void Empty() 168 { 169 ::SysFreeString(m_str); 170 m_str = NULL; 171 } 172}; 173 174 175class CMyComBSTR_Wipe: public CMyComBSTR 176{ 177 Z7_CLASS_NO_COPY(CMyComBSTR_Wipe) 178public: 179 CMyComBSTR_Wipe(): CMyComBSTR() {} 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 Z7_COM_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 We can use virtual ~CMyUnknownImp() to disable warning 194 "class has virtual functions, but destructor is not virtual". 195 Also we can use virtual ~IUnknown() {} in MyWindows.h 196*/ 197 198class CMyUnknownImp 199{ 200 Z7_CLASS_NO_COPY(CMyUnknownImp) 201protected: 202 ULONG _m_RefCount; 203 CMyUnknownImp(): _m_RefCount(0) {} 204 205 #ifdef _WIN32 206 #if defined(__GNUC__) || defined(__clang__) 207 // virtual ~CMyUnknownImp() {} // to disable GCC/CLANG varnings 208 #endif 209 #endif 210}; 211 212 213 214#define Z7_COM_QI_BEGIN \ 215 private: STDMETHOD(QueryInterface) (REFGUID iid, void **outObject) throw() Z7_override Z7_final \ 216 { *outObject = NULL; 217 218#define Z7_COM_QI_ENTRY(i) \ 219 else if (iid == IID_ ## i) \ 220 { i *ti = this; *outObject = ti; } 221// { *outObject = (void *)(i *)this; } 222 223#define Z7_COM_QI_ENTRY_UNKNOWN_0 \ 224 if (iid == IID_IUnknown) \ 225 { IUnknown *tu = this; *outObject = tu; } 226 227#define Z7_COM_QI_ENTRY_UNKNOWN(i) \ 228 if (iid == IID_IUnknown) \ 229 { i *ti = this; IUnknown *tu = ti; *outObject = tu; } 230// { *outObject = (void *)(IUnknown *)(i *)this; } 231 232#define Z7_COM_QI_BEGIN2(i) \ 233 Z7_COM_QI_BEGIN \ 234 Z7_COM_QI_ENTRY_UNKNOWN(i) \ 235 Z7_COM_QI_ENTRY(i) 236 237#define Z7_COM_QI_END \ 238 else return E_NOINTERFACE; \ 239 ++_m_RefCount; /* AddRef(); */ return S_OK; } 240 241#define Z7_COM_ADDREF_RELEASE \ 242 private: \ 243 STDMETHOD_(ULONG, AddRef)() throw() Z7_override Z7_final \ 244 { return ++_m_RefCount; } \ 245 STDMETHOD_(ULONG, Release)() throw() Z7_override Z7_final \ 246 { if (--_m_RefCount != 0) return _m_RefCount; delete this; return 0; } \ 247 248#define Z7_COM_UNKNOWN_IMP_SPEC(i) \ 249 Z7_COM_QI_BEGIN \ 250 i \ 251 Z7_COM_QI_END \ 252 Z7_COM_ADDREF_RELEASE 253 254 255#define Z7_COM_UNKNOWN_IMP_0 \ 256 Z7_COM_QI_BEGIN \ 257 Z7_COM_QI_ENTRY_UNKNOWN_0 \ 258 Z7_COM_QI_END \ 259 Z7_COM_ADDREF_RELEASE 260 261#define Z7_COM_UNKNOWN_IMP_1(i) \ 262 Z7_COM_UNKNOWN_IMP_SPEC( \ 263 Z7_COM_QI_ENTRY_UNKNOWN(i) \ 264 Z7_COM_QI_ENTRY(i) \ 265 ) 266 267#define Z7_COM_UNKNOWN_IMP_2(i1, i2) \ 268 Z7_COM_UNKNOWN_IMP_SPEC( \ 269 Z7_COM_QI_ENTRY_UNKNOWN(i1) \ 270 Z7_COM_QI_ENTRY(i1) \ 271 Z7_COM_QI_ENTRY(i2) \ 272 ) 273 274#define Z7_COM_UNKNOWN_IMP_3(i1, i2, i3) \ 275 Z7_COM_UNKNOWN_IMP_SPEC( \ 276 Z7_COM_QI_ENTRY_UNKNOWN(i1) \ 277 Z7_COM_QI_ENTRY(i1) \ 278 Z7_COM_QI_ENTRY(i2) \ 279 Z7_COM_QI_ENTRY(i3) \ 280 ) 281 282#define Z7_COM_UNKNOWN_IMP_4(i1, i2, i3, i4) \ 283 Z7_COM_UNKNOWN_IMP_SPEC( \ 284 Z7_COM_QI_ENTRY_UNKNOWN(i1) \ 285 Z7_COM_QI_ENTRY(i1) \ 286 Z7_COM_QI_ENTRY(i2) \ 287 Z7_COM_QI_ENTRY(i3) \ 288 Z7_COM_QI_ENTRY(i4) \ 289 ) 290 291#define Z7_COM_UNKNOWN_IMP_5(i1, i2, i3, i4, i5) \ 292 Z7_COM_UNKNOWN_IMP_SPEC( \ 293 Z7_COM_QI_ENTRY_UNKNOWN(i1) \ 294 Z7_COM_QI_ENTRY(i1) \ 295 Z7_COM_QI_ENTRY(i2) \ 296 Z7_COM_QI_ENTRY(i3) \ 297 Z7_COM_QI_ENTRY(i4) \ 298 Z7_COM_QI_ENTRY(i5) \ 299 ) 300 301#define Z7_COM_UNKNOWN_IMP_6(i1, i2, i3, i4, i5, i6) \ 302 Z7_COM_UNKNOWN_IMP_SPEC( \ 303 Z7_COM_QI_ENTRY_UNKNOWN(i1) \ 304 Z7_COM_QI_ENTRY(i1) \ 305 Z7_COM_QI_ENTRY(i2) \ 306 Z7_COM_QI_ENTRY(i3) \ 307 Z7_COM_QI_ENTRY(i4) \ 308 Z7_COM_QI_ENTRY(i5) \ 309 Z7_COM_QI_ENTRY(i6) \ 310 ) 311 312#define Z7_COM_UNKNOWN_IMP_7(i1, i2, i3, i4, i5, i6, i7) \ 313 Z7_COM_UNKNOWN_IMP_SPEC( \ 314 Z7_COM_QI_ENTRY_UNKNOWN(i1) \ 315 Z7_COM_QI_ENTRY(i1) \ 316 Z7_COM_QI_ENTRY(i2) \ 317 Z7_COM_QI_ENTRY(i3) \ 318 Z7_COM_QI_ENTRY(i4) \ 319 Z7_COM_QI_ENTRY(i5) \ 320 Z7_COM_QI_ENTRY(i6) \ 321 Z7_COM_QI_ENTRY(i7) \ 322 ) 323 324 325#define Z7_IFACES_IMP_UNK_1(i1) \ 326 Z7_COM_UNKNOWN_IMP_1(i1) \ 327 Z7_IFACE_COM7_IMP(i1) \ 328 329#define Z7_IFACES_IMP_UNK_2(i1, i2) \ 330 Z7_COM_UNKNOWN_IMP_2(i1, i2) \ 331 Z7_IFACE_COM7_IMP(i1) \ 332 Z7_IFACE_COM7_IMP(i2) \ 333 334#define Z7_IFACES_IMP_UNK_3(i1, i2, i3) \ 335 Z7_COM_UNKNOWN_IMP_3(i1, i2, i3) \ 336 Z7_IFACE_COM7_IMP(i1) \ 337 Z7_IFACE_COM7_IMP(i2) \ 338 Z7_IFACE_COM7_IMP(i3) \ 339 340#define Z7_IFACES_IMP_UNK_4(i1, i2, i3, i4) \ 341 Z7_COM_UNKNOWN_IMP_4(i1, i2, i3, i4) \ 342 Z7_IFACE_COM7_IMP(i1) \ 343 Z7_IFACE_COM7_IMP(i2) \ 344 Z7_IFACE_COM7_IMP(i3) \ 345 Z7_IFACE_COM7_IMP(i4) \ 346 347#define Z7_IFACES_IMP_UNK_5(i1, i2, i3, i4, i5) \ 348 Z7_COM_UNKNOWN_IMP_5(i1, i2, i3, i4, i5) \ 349 Z7_IFACE_COM7_IMP(i1) \ 350 Z7_IFACE_COM7_IMP(i2) \ 351 Z7_IFACE_COM7_IMP(i3) \ 352 Z7_IFACE_COM7_IMP(i4) \ 353 Z7_IFACE_COM7_IMP(i5) \ 354 355#define Z7_IFACES_IMP_UNK_6(i1, i2, i3, i4, i5, i6) \ 356 Z7_COM_UNKNOWN_IMP_6(i1, i2, i3, i4, i5, i6) \ 357 Z7_IFACE_COM7_IMP(i1) \ 358 Z7_IFACE_COM7_IMP(i2) \ 359 Z7_IFACE_COM7_IMP(i3) \ 360 Z7_IFACE_COM7_IMP(i4) \ 361 Z7_IFACE_COM7_IMP(i5) \ 362 Z7_IFACE_COM7_IMP(i6) \ 363 364 365#define Z7_CLASS_IMP_COM_0(c) \ 366 Z7_class_final(c) : \ 367 public IUnknown, \ 368 public CMyUnknownImp { \ 369 Z7_COM_UNKNOWN_IMP_0 \ 370 private: 371 372#define Z7_CLASS_IMP_COM_1(c, i1) \ 373 Z7_class_final(c) : \ 374 public i1, \ 375 public CMyUnknownImp { \ 376 Z7_IFACES_IMP_UNK_1(i1) \ 377 private: 378 379#define Z7_CLASS_IMP_COM_2(c, i1, i2) \ 380 Z7_class_final(c) : \ 381 public i1, \ 382 public i2, \ 383 public CMyUnknownImp { \ 384 Z7_IFACES_IMP_UNK_2(i1, i2) \ 385 private: 386 387#define Z7_CLASS_IMP_COM_3(c, i1, i2, i3) \ 388 Z7_class_final(c) : \ 389 public i1, \ 390 public i2, \ 391 public i3, \ 392 public CMyUnknownImp { \ 393 Z7_IFACES_IMP_UNK_3(i1, i2, i3) \ 394 private: 395 396#define Z7_CLASS_IMP_COM_4(c, i1, i2, i3, i4) \ 397 Z7_class_final(c) : \ 398 public i1, \ 399 public i2, \ 400 public i3, \ 401 public i4, \ 402 public CMyUnknownImp { \ 403 Z7_IFACES_IMP_UNK_4(i1, i2, i3, i4) \ 404 private: 405 406#define Z7_CLASS_IMP_COM_5(c, i1, i2, i3, i4, i5) \ 407 Z7_class_final(c) : \ 408 public i1, \ 409 public i2, \ 410 public i3, \ 411 public i4, \ 412 public i5, \ 413 public CMyUnknownImp { \ 414 Z7_IFACES_IMP_UNK_5(i1, i2, i3, i4, i5) \ 415 private: 416 417#define Z7_CLASS_IMP_COM_6(c, i1, i2, i3, i4, i5, i6) \ 418 Z7_class_final(c) : \ 419 public i1, \ 420 public i2, \ 421 public i3, \ 422 public i4, \ 423 public i5, \ 424 public i6, \ 425 public CMyUnknownImp { \ 426 Z7_IFACES_IMP_UNK_6(i1, i2, i3, i4, i5, i6) \ 427 private: 428 429 430/* 431#define Z7_CLASS_IMP_NOQIB_0(c) \ 432 Z7_class_final(c) : \ 433 public IUnknown, \ 434 public CMyUnknownImp { \ 435 Z7_COM_UNKNOWN_IMP_0 \ 436 private: 437*/ 438 439#define Z7_CLASS_IMP_NOQIB_1(c, i1) \ 440 Z7_class_final(c) : \ 441 public i1, \ 442 public CMyUnknownImp { \ 443 Z7_COM_UNKNOWN_IMP_0 \ 444 Z7_IFACE_COM7_IMP(i1) \ 445 private: 446 447#define Z7_CLASS_IMP_NOQIB_2(c, i1, i2) \ 448 Z7_class_final(c) : \ 449 public i1, \ 450 public i2, \ 451 public CMyUnknownImp { \ 452 Z7_COM_UNKNOWN_IMP_1(i2) \ 453 Z7_IFACE_COM7_IMP(i1) \ 454 Z7_IFACE_COM7_IMP(i2) \ 455 private: 456 457#define Z7_CLASS_IMP_NOQIB_3(c, i1, i2, i3) \ 458 Z7_class_final(c) : \ 459 public i1, \ 460 public i2, \ 461 public i3, \ 462 public CMyUnknownImp { \ 463 Z7_COM_UNKNOWN_IMP_2(i2, i3) \ 464 Z7_IFACE_COM7_IMP(i1) \ 465 Z7_IFACE_COM7_IMP(i2) \ 466 Z7_IFACE_COM7_IMP(i3) \ 467 private: 468 469#define Z7_CLASS_IMP_NOQIB_4(c, i1, i2, i3, i4) \ 470 Z7_class_final(c) : \ 471 public i1, \ 472 public i2, \ 473 public i3, \ 474 public i4, \ 475 public CMyUnknownImp { \ 476 Z7_COM_UNKNOWN_IMP_3(i2, i3, i4) \ 477 Z7_IFACE_COM7_IMP(i1) \ 478 Z7_IFACE_COM7_IMP(i2) \ 479 Z7_IFACE_COM7_IMP(i3) \ 480 Z7_IFACE_COM7_IMP(i4) \ 481 482/* 483#define Z7_CLASS_IMP_NOQIB_5(c, i1, i2, i3, i4, i5) \ 484 Z7_class_final(c) : \ 485 public i1, \ 486 public i2, \ 487 public i3, \ 488 public i4, \ 489 public i5, \ 490 public CMyUnknownImp { \ 491 Z7_COM_UNKNOWN_IMP_4(i2, i3, i4, i5) \ 492 Z7_IFACE_COM7_IMP(i1) \ 493 Z7_IFACE_COM7_IMP(i2) \ 494 Z7_IFACE_COM7_IMP(i3) \ 495 Z7_IFACE_COM7_IMP(i4) \ 496 Z7_IFACE_COM7_IMP(i5) \ 497*/ 498 499 500#define Z7_CLASS_IMP_IInStream(c) \ 501 class c Z7_final : \ 502 public IInStream, \ 503 public CMyUnknownImp { \ 504 Z7_IFACES_IMP_UNK_2(ISequentialInStream, IInStream) \ 505 506 507#define k_My_HRESULT_WritingWasCut 0x20000010 508 509#endif 510