1// MyCom.h
2
3#ifndef __MYCOM_H
4#define __MYCOM_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
12template <class T>
13class CMyComPtr
14{
15  T* _p;
16public:
17  // typedef T _PtrClass;
18  CMyComPtr() { _p = NULL;}
19  CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); }
20  CMyComPtr(const CMyComPtr<T>& lp)
21  {
22    if ((_p = lp._p) != NULL)
23      _p->AddRef();
24  }
25  ~CMyComPtr() { if (_p) _p->Release(); }
26  void Release() { if (_p) { _p->Release(); _p = NULL; } }
27  operator T*() const {  return (T*)_p;  }
28  // T& operator*() const {  return *_p; }
29  T** operator&() { return &_p; }
30  T* operator->() const { return _p; }
31  T* operator=(T* p)
32  {
33    if (p != 0)
34      p->AddRef();
35    if (_p)
36      _p->Release();
37    _p = p;
38    return p;
39  }
40  T* operator=(const CMyComPtr<T>& lp) { return (*this = lp._p); }
41  bool operator!() const { return (_p == NULL); }
42  // bool operator==(T* pT) const {  return _p == pT; }
43  // Compare two objects for equivalence
44  void Attach(T* p2)
45  {
46    Release();
47    _p = p2;
48  }
49  T* Detach()
50  {
51    T* pt = _p;
52    _p = NULL;
53    return pt;
54  }
55  #ifdef _WIN32
56  HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
57  {
58    return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p);
59  }
60  #endif
61  /*
62  HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
63  {
64    CLSID clsid;
65    HRESULT hr = CLSIDFromProgID(szProgID, &clsid);
66    ATLASSERT(_p == NULL);
67    if (SUCCEEDED(hr))
68      hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p);
69    return hr;
70  }
71  */
72  template <class Q>
73  HRESULT QueryInterface(REFGUID iid, Q** pp) const
74  {
75    return _p->QueryInterface(iid, (void**)pp);
76  }
77};
78
79//////////////////////////////////////////////////////////
80
81inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr)
82{
83  *bstr = ::SysAllocString(src);
84  return (*bstr != 0) ? S_OK : E_OUTOFMEMORY;
85}
86
87class CMyComBSTR
88{
89public:
90  BSTR m_str;
91  CMyComBSTR(): m_str(NULL) {}
92  CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); }
93  // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); }
94  // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize);  }
95  CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); }
96  /*
97  CMyComBSTR(REFGUID src)
98  {
99    LPOLESTR szGuid;
100    StringFromCLSID(src, &szGuid);
101    m_str = ::SysAllocString(szGuid);
102    CoTaskMemFree(szGuid);
103  }
104  */
105  ~CMyComBSTR() { ::SysFreeString(m_str); }
106  CMyComBSTR& operator=(const CMyComBSTR& src)
107  {
108    if (m_str != src.m_str)
109    {
110      if (m_str)
111        ::SysFreeString(m_str);
112      m_str = src.MyCopy();
113    }
114    return *this;
115  }
116  CMyComBSTR& operator=(LPCOLESTR src)
117  {
118    ::SysFreeString(m_str);
119    m_str = ::SysAllocString(src);
120    return *this;
121  }
122  unsigned int Length() const { return ::SysStringLen(m_str); }
123  operator BSTR() const { return m_str; }
124  BSTR* operator&() { return &m_str; }
125  BSTR MyCopy() const
126  {
127    int byteLen = ::SysStringByteLen(m_str);
128    BSTR res = ::SysAllocStringByteLen(NULL, byteLen);
129    memcpy(res, m_str, byteLen);
130    return res;
131  }
132  /*
133  void Attach(BSTR src) { m_str = src; }
134  BSTR Detach()
135  {
136    BSTR s = m_str;
137    m_str = NULL;
138    return s;
139  }
140  */
141  void Empty()
142  {
143    ::SysFreeString(m_str);
144    m_str = NULL;
145  }
146  bool operator!() const {  return (m_str == NULL); }
147};
148
149//////////////////////////////////////////////////////////
150
151class CMyUnknownImp
152{
153public:
154  ULONG __m_RefCount;
155  CMyUnknownImp(): __m_RefCount(0) {}
156};
157
158#define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \
159    (REFGUID iid, void **outObject) {
160
161#define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \
162    { *outObject = (void *)(i *)this; AddRef(); return S_OK; }
163
164#define MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) if (iid == IID_IUnknown) \
165    { *outObject = (void *)(IUnknown *)(i *)this; AddRef(); return S_OK; }
166
167#define MY_QUERYINTERFACE_BEGIN2(i) MY_QUERYINTERFACE_BEGIN \
168    MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \
169    MY_QUERYINTERFACE_ENTRY(i)
170
171#define MY_QUERYINTERFACE_END return E_NOINTERFACE; }
172
173#define MY_ADDREF_RELEASE \
174STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \
175STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0)  \
176  return __m_RefCount; delete this; return 0; }
177
178#define MY_UNKNOWN_IMP_SPEC(i) \
179  MY_QUERYINTERFACE_BEGIN \
180  i \
181  MY_QUERYINTERFACE_END \
182  MY_ADDREF_RELEASE
183
184
185#define MY_UNKNOWN_IMP MY_QUERYINTERFACE_BEGIN \
186  MY_QUERYINTERFACE_ENTRY_UNKNOWN(IUnknown) \
187  MY_QUERYINTERFACE_END \
188  MY_ADDREF_RELEASE
189
190#define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \
191  MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \
192  MY_QUERYINTERFACE_ENTRY(i) \
193  )
194
195#define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \
196  MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
197  MY_QUERYINTERFACE_ENTRY(i1) \
198  MY_QUERYINTERFACE_ENTRY(i2) \
199  )
200
201#define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \
202  MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
203  MY_QUERYINTERFACE_ENTRY(i1) \
204  MY_QUERYINTERFACE_ENTRY(i2) \
205  MY_QUERYINTERFACE_ENTRY(i3) \
206  )
207
208#define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \
209  MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
210  MY_QUERYINTERFACE_ENTRY(i1) \
211  MY_QUERYINTERFACE_ENTRY(i2) \
212  MY_QUERYINTERFACE_ENTRY(i3) \
213  MY_QUERYINTERFACE_ENTRY(i4) \
214  )
215
216#define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \
217  MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
218  MY_QUERYINTERFACE_ENTRY(i1) \
219  MY_QUERYINTERFACE_ENTRY(i2) \
220  MY_QUERYINTERFACE_ENTRY(i3) \
221  MY_QUERYINTERFACE_ENTRY(i4) \
222  MY_QUERYINTERFACE_ENTRY(i5) \
223  )
224
225#endif
226