// MyCom.h #ifndef ZIP7_INC_MY_COM_H #define ZIP7_INC_MY_COM_H #include "MyWindows.h" #include "MyTypes.h" template class CMyComPtr { T* _p; public: CMyComPtr(): _p(NULL) {} CMyComPtr(T* p) throw() { if ((_p = p) != NULL) p->AddRef(); } CMyComPtr(const CMyComPtr& lp) throw() { if ((_p = lp._p) != NULL) _p->AddRef(); } ~CMyComPtr() { if (_p) _p->Release(); } void Release() { if (_p) { _p->Release(); _p = NULL; } } operator T*() const { return (T*)_p; } // T& operator*() const { return *_p; } T** operator&() { return &_p; } T* operator->() const { return _p; } T* operator=(T* p) { if (p) p->AddRef(); if (_p) _p->Release(); _p = p; return p; } T* operator=(const CMyComPtr& lp) { return (*this = lp._p); } bool operator!() const { return (_p == NULL); } // bool operator==(T* pT) const { return _p == pT; } void Attach(T* p2) { Release(); _p = p2; } T* Detach() { T* pt = _p; _p = NULL; return pt; } #ifdef _WIN32 HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p); } #endif /* HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { CLSID clsid; HRESULT hr = CLSIDFromProgID(szProgID, &clsid); ATLASSERT(_p == NULL); if (SUCCEEDED(hr)) hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p); return hr; } */ template HRESULT QueryInterface(REFGUID iid, Q** pp) const throw() { // if (*pp) throw 20220216; // for debug return _p->QueryInterface(iid, (void**)pp); } }; #define Z7_DECL_CMyComPtr_QI_FROM(i, v, unk) \ CMyComPtr v; (unk)->QueryInterface(IID_ ## i, (void **)&v); ////////////////////////////////////////////////////////// inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr) { *bstr = ::SysAllocString(src); return (*bstr) ? S_OK : E_OUTOFMEMORY; } class CMyComBSTR { BSTR m_str; Z7_CLASS_NO_COPY(CMyComBSTR) public: CMyComBSTR(): m_str(NULL) {} ~CMyComBSTR() { ::SysFreeString(m_str); } BSTR* operator&() { return &m_str; } operator LPCOLESTR() const { return m_str; } // operator bool() const { return m_str != NULL; } // bool operator!() const { return m_str == NULL; } void Wipe_and_Free() { if (m_str) { memset(m_str, 0, ::SysStringLen(m_str) * sizeof(*m_str)); Empty(); } } private: // operator BSTR() const { return m_str; } CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); } // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); } // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); } // CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); } /* CMyComBSTR(REFGUID src) { LPOLESTR szGuid; StringFromCLSID(src, &szGuid); m_str = ::SysAllocString(szGuid); CoTaskMemFree(szGuid); } */ /* CMyComBSTR& operator=(const CMyComBSTR& src) { if (m_str != src.m_str) { if (m_str) ::SysFreeString(m_str); m_str = src.MyCopy(); } return *this; } */ CMyComBSTR& operator=(LPCOLESTR src) { ::SysFreeString(m_str); m_str = ::SysAllocString(src); return *this; } unsigned Len() const { return ::SysStringLen(m_str); } BSTR MyCopy() const { // We don't support Byte BSTRs here return ::SysAllocStringLen(m_str, ::SysStringLen(m_str)); /* UINT byteLen = ::SysStringByteLen(m_str); BSTR res = ::SysAllocStringByteLen(NULL, byteLen); if (res && byteLen != 0 && m_str) memcpy(res, m_str, byteLen); return res; */ } /* void Attach(BSTR src) { m_str = src; } BSTR Detach() { BSTR s = m_str; m_str = NULL; return s; } */ void Empty() { ::SysFreeString(m_str); m_str = NULL; } }; class CMyComBSTR_Wipe: public CMyComBSTR { Z7_CLASS_NO_COPY(CMyComBSTR_Wipe) public: CMyComBSTR_Wipe(): CMyComBSTR() {} ~CMyComBSTR_Wipe() { Wipe_and_Free(); } }; /* If CMyUnknownImp doesn't use virtual destructor, the code size is smaller. But if some class_1 derived from CMyUnknownImp uses Z7_COM_ADDREF_RELEASE and IUnknown::Release() and some another class_2 is derived from class_1, then class_1 must use virtual destructor: virtual ~class_1(); In that case, class_1::Release() calls correct destructor of class_2. We can use virtual ~CMyUnknownImp() to disable warning "class has virtual functions, but destructor is not virtual". Also we can use virtual ~IUnknown() {} in MyWindows.h */ class CMyUnknownImp { Z7_CLASS_NO_COPY(CMyUnknownImp) protected: ULONG _m_RefCount; CMyUnknownImp(): _m_RefCount(0) {} #ifdef _WIN32 #if defined(__GNUC__) || defined(__clang__) // virtual ~CMyUnknownImp() {} // to disable GCC/CLANG warnings #endif #endif }; #define Z7_COM_QI_BEGIN \ private: STDMETHOD(QueryInterface) (REFGUID iid, void **outObject) throw() Z7_override Z7_final \ { *outObject = NULL; #define Z7_COM_QI_ENTRY(i) \ else if (iid == IID_ ## i) \ { i *ti = this; *outObject = ti; } // { *outObject = (void *)(i *)this; } #define Z7_COM_QI_ENTRY_UNKNOWN_0 \ if (iid == IID_IUnknown) \ { IUnknown *tu = this; *outObject = tu; } #define Z7_COM_QI_ENTRY_UNKNOWN(i) \ if (iid == IID_IUnknown) \ { i *ti = this; IUnknown *tu = ti; *outObject = tu; } // { *outObject = (void *)(IUnknown *)(i *)this; } #define Z7_COM_QI_BEGIN2(i) \ Z7_COM_QI_BEGIN \ Z7_COM_QI_ENTRY_UNKNOWN(i) \ Z7_COM_QI_ENTRY(i) #define Z7_COM_QI_END \ else return E_NOINTERFACE; \ ++_m_RefCount; /* AddRef(); */ return S_OK; } #define Z7_COM_ADDREF_RELEASE \ private: \ STDMETHOD_(ULONG, AddRef)() throw() Z7_override Z7_final \ { return ++_m_RefCount; } \ STDMETHOD_(ULONG, Release)() throw() Z7_override Z7_final \ { if (--_m_RefCount != 0) return _m_RefCount; delete this; return 0; } \ #define Z7_COM_UNKNOWN_IMP_SPEC(i) \ Z7_COM_QI_BEGIN \ i \ Z7_COM_QI_END \ Z7_COM_ADDREF_RELEASE #define Z7_COM_UNKNOWN_IMP_0 \ Z7_COM_QI_BEGIN \ Z7_COM_QI_ENTRY_UNKNOWN_0 \ Z7_COM_QI_END \ Z7_COM_ADDREF_RELEASE #define Z7_COM_UNKNOWN_IMP_1(i) \ Z7_COM_UNKNOWN_IMP_SPEC( \ Z7_COM_QI_ENTRY_UNKNOWN(i) \ Z7_COM_QI_ENTRY(i) \ ) #define Z7_COM_UNKNOWN_IMP_2(i1, i2) \ Z7_COM_UNKNOWN_IMP_SPEC( \ Z7_COM_QI_ENTRY_UNKNOWN(i1) \ Z7_COM_QI_ENTRY(i1) \ Z7_COM_QI_ENTRY(i2) \ ) #define Z7_COM_UNKNOWN_IMP_3(i1, i2, i3) \ Z7_COM_UNKNOWN_IMP_SPEC( \ Z7_COM_QI_ENTRY_UNKNOWN(i1) \ Z7_COM_QI_ENTRY(i1) \ Z7_COM_QI_ENTRY(i2) \ Z7_COM_QI_ENTRY(i3) \ ) #define Z7_COM_UNKNOWN_IMP_4(i1, i2, i3, i4) \ Z7_COM_UNKNOWN_IMP_SPEC( \ Z7_COM_QI_ENTRY_UNKNOWN(i1) \ Z7_COM_QI_ENTRY(i1) \ Z7_COM_QI_ENTRY(i2) \ Z7_COM_QI_ENTRY(i3) \ Z7_COM_QI_ENTRY(i4) \ ) #define Z7_COM_UNKNOWN_IMP_5(i1, i2, i3, i4, i5) \ Z7_COM_UNKNOWN_IMP_SPEC( \ Z7_COM_QI_ENTRY_UNKNOWN(i1) \ Z7_COM_QI_ENTRY(i1) \ Z7_COM_QI_ENTRY(i2) \ Z7_COM_QI_ENTRY(i3) \ Z7_COM_QI_ENTRY(i4) \ Z7_COM_QI_ENTRY(i5) \ ) #define Z7_COM_UNKNOWN_IMP_6(i1, i2, i3, i4, i5, i6) \ Z7_COM_UNKNOWN_IMP_SPEC( \ Z7_COM_QI_ENTRY_UNKNOWN(i1) \ Z7_COM_QI_ENTRY(i1) \ Z7_COM_QI_ENTRY(i2) \ Z7_COM_QI_ENTRY(i3) \ Z7_COM_QI_ENTRY(i4) \ Z7_COM_QI_ENTRY(i5) \ Z7_COM_QI_ENTRY(i6) \ ) #define Z7_COM_UNKNOWN_IMP_7(i1, i2, i3, i4, i5, i6, i7) \ Z7_COM_UNKNOWN_IMP_SPEC( \ Z7_COM_QI_ENTRY_UNKNOWN(i1) \ Z7_COM_QI_ENTRY(i1) \ Z7_COM_QI_ENTRY(i2) \ Z7_COM_QI_ENTRY(i3) \ Z7_COM_QI_ENTRY(i4) \ Z7_COM_QI_ENTRY(i5) \ Z7_COM_QI_ENTRY(i6) \ Z7_COM_QI_ENTRY(i7) \ ) #define Z7_IFACES_IMP_UNK_1(i1) \ Z7_COM_UNKNOWN_IMP_1(i1) \ Z7_IFACE_COM7_IMP(i1) \ #define Z7_IFACES_IMP_UNK_2(i1, i2) \ Z7_COM_UNKNOWN_IMP_2(i1, i2) \ Z7_IFACE_COM7_IMP(i1) \ Z7_IFACE_COM7_IMP(i2) \ #define Z7_IFACES_IMP_UNK_3(i1, i2, i3) \ Z7_COM_UNKNOWN_IMP_3(i1, i2, i3) \ Z7_IFACE_COM7_IMP(i1) \ Z7_IFACE_COM7_IMP(i2) \ Z7_IFACE_COM7_IMP(i3) \ #define Z7_IFACES_IMP_UNK_4(i1, i2, i3, i4) \ Z7_COM_UNKNOWN_IMP_4(i1, i2, i3, i4) \ Z7_IFACE_COM7_IMP(i1) \ Z7_IFACE_COM7_IMP(i2) \ Z7_IFACE_COM7_IMP(i3) \ Z7_IFACE_COM7_IMP(i4) \ #define Z7_IFACES_IMP_UNK_5(i1, i2, i3, i4, i5) \ Z7_COM_UNKNOWN_IMP_5(i1, i2, i3, i4, i5) \ Z7_IFACE_COM7_IMP(i1) \ Z7_IFACE_COM7_IMP(i2) \ Z7_IFACE_COM7_IMP(i3) \ Z7_IFACE_COM7_IMP(i4) \ Z7_IFACE_COM7_IMP(i5) \ #define Z7_IFACES_IMP_UNK_6(i1, i2, i3, i4, i5, i6) \ Z7_COM_UNKNOWN_IMP_6(i1, i2, i3, i4, i5, i6) \ Z7_IFACE_COM7_IMP(i1) \ Z7_IFACE_COM7_IMP(i2) \ Z7_IFACE_COM7_IMP(i3) \ Z7_IFACE_COM7_IMP(i4) \ Z7_IFACE_COM7_IMP(i5) \ Z7_IFACE_COM7_IMP(i6) \ #define Z7_CLASS_IMP_COM_0(c) \ Z7_class_final(c) : \ public IUnknown, \ public CMyUnknownImp { \ Z7_COM_UNKNOWN_IMP_0 \ private: #define Z7_CLASS_IMP_COM_1(c, i1) \ Z7_class_final(c) : \ public i1, \ public CMyUnknownImp { \ Z7_IFACES_IMP_UNK_1(i1) \ private: #define Z7_CLASS_IMP_COM_2(c, i1, i2) \ Z7_class_final(c) : \ public i1, \ public i2, \ public CMyUnknownImp { \ Z7_IFACES_IMP_UNK_2(i1, i2) \ private: #define Z7_CLASS_IMP_COM_3(c, i1, i2, i3) \ Z7_class_final(c) : \ public i1, \ public i2, \ public i3, \ public CMyUnknownImp { \ Z7_IFACES_IMP_UNK_3(i1, i2, i3) \ private: #define Z7_CLASS_IMP_COM_4(c, i1, i2, i3, i4) \ Z7_class_final(c) : \ public i1, \ public i2, \ public i3, \ public i4, \ public CMyUnknownImp { \ Z7_IFACES_IMP_UNK_4(i1, i2, i3, i4) \ private: #define Z7_CLASS_IMP_COM_5(c, i1, i2, i3, i4, i5) \ Z7_class_final(c) : \ public i1, \ public i2, \ public i3, \ public i4, \ public i5, \ public CMyUnknownImp { \ Z7_IFACES_IMP_UNK_5(i1, i2, i3, i4, i5) \ private: #define Z7_CLASS_IMP_COM_6(c, i1, i2, i3, i4, i5, i6) \ Z7_class_final(c) : \ public i1, \ public i2, \ public i3, \ public i4, \ public i5, \ public i6, \ public CMyUnknownImp { \ Z7_IFACES_IMP_UNK_6(i1, i2, i3, i4, i5, i6) \ private: /* #define Z7_CLASS_IMP_NOQIB_0(c) \ Z7_class_final(c) : \ public IUnknown, \ public CMyUnknownImp { \ Z7_COM_UNKNOWN_IMP_0 \ private: */ #define Z7_CLASS_IMP_NOQIB_1(c, i1) \ Z7_class_final(c) : \ public i1, \ public CMyUnknownImp { \ Z7_COM_UNKNOWN_IMP_0 \ Z7_IFACE_COM7_IMP(i1) \ private: #define Z7_CLASS_IMP_NOQIB_2(c, i1, i2) \ Z7_class_final(c) : \ public i1, \ public i2, \ public CMyUnknownImp { \ Z7_COM_UNKNOWN_IMP_1(i2) \ Z7_IFACE_COM7_IMP(i1) \ Z7_IFACE_COM7_IMP(i2) \ private: #define Z7_CLASS_IMP_NOQIB_3(c, i1, i2, i3) \ Z7_class_final(c) : \ public i1, \ public i2, \ public i3, \ public CMyUnknownImp { \ Z7_COM_UNKNOWN_IMP_2(i2, i3) \ Z7_IFACE_COM7_IMP(i1) \ Z7_IFACE_COM7_IMP(i2) \ Z7_IFACE_COM7_IMP(i3) \ private: #define Z7_CLASS_IMP_NOQIB_4(c, i1, i2, i3, i4) \ Z7_class_final(c) : \ public i1, \ public i2, \ public i3, \ public i4, \ public CMyUnknownImp { \ Z7_COM_UNKNOWN_IMP_3(i2, i3, i4) \ Z7_IFACE_COM7_IMP(i1) \ Z7_IFACE_COM7_IMP(i2) \ Z7_IFACE_COM7_IMP(i3) \ Z7_IFACE_COM7_IMP(i4) \ /* #define Z7_CLASS_IMP_NOQIB_5(c, i1, i2, i3, i4, i5) \ Z7_class_final(c) : \ public i1, \ public i2, \ public i3, \ public i4, \ public i5, \ public CMyUnknownImp { \ Z7_COM_UNKNOWN_IMP_4(i2, i3, i4, i5) \ Z7_IFACE_COM7_IMP(i1) \ Z7_IFACE_COM7_IMP(i2) \ Z7_IFACE_COM7_IMP(i3) \ Z7_IFACE_COM7_IMP(i4) \ Z7_IFACE_COM7_IMP(i5) \ */ #define Z7_CLASS_IMP_IInStream(c) \ class c Z7_final : \ public IInStream, \ public CMyUnknownImp { \ Z7_IFACES_IMP_UNK_2(ISequentialInStream, IInStream) \ #define k_My_HRESULT_WritingWasCut 0x20000010 #endif