automatically initialize m_cRef to 0 (patch 575011 + more)
[wxWidgets.git] / include / wx / msw / ole / oleutils.h
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: oleutils.h
3 // Purpose: OLE helper routines, OLE debugging support &c
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 19.02.1998
7 // RCS-ID: $Id$
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 #ifndef _WX_OLEUTILS_H
13 #define _WX_OLEUTILS_H
14
15 #ifdef __GNUG__
16 #pragma interface "oleutils.h"
17 #endif
18
19 #include "wx/defs.h"
20
21 #if wxUSE_NORLANDER_HEADERS
22 #include <ole2.h>
23 #endif
24
25 // ============================================================================
26 // General purpose functions and macros
27 // ============================================================================
28
29 // ----------------------------------------------------------------------------
30 // misc helper functions/macros
31 // ----------------------------------------------------------------------------
32
33 // release the interface pointer (if !NULL)
34 inline void ReleaseInterface(IUnknown *pIUnk)
35 {
36 if ( pIUnk != NULL )
37 pIUnk->Release();
38 }
39
40 // release the interface pointer (if !NULL) and make it NULL
41 #define RELEASE_AND_NULL(p) if ( (p) != NULL ) { p->Release(); p = NULL; };
42
43 // return TRUE if the iid is in the array
44 extern bool IsIidFromList(REFIID riid, const IID *aIids[], size_t nCount);
45
46 // ============================================================================
47 // IUnknown implementation helpers
48 // ============================================================================
49
50 /*
51 The most dumb implementation of IUnknown methods. We don't support
52 aggregation nor containment, but for 99% of cases this simple
53 implementation is quite enough.
54
55 Usage is trivial: here is all you should have
56 1) DECLARE_IUNKNOWN_METHODS in your (IUnknown derived!) class declaration
57 2) BEGIN/END_IID_TABLE with ADD_IID in between for all interfaces you
58 support (at least all for which you intent to return 'this' from QI,
59 i.e. you should derive from IFoo if you have ADD_IID(Foo)) somewhere else
60 3) IMPLEMENT_IUNKNOWN_METHODS somewhere also
61
62 These macros are quite simple: AddRef and Release are trivial and QI does
63 lookup in a static member array of IIDs and returns 'this' if it founds
64 the requested interface in it or E_NOINTERFACE if not.
65 */
66
67 /*
68 wxAutoULong: this class is used for automatically initalising m_cRef to 0
69 */
70 class wxAutoULong
71 {
72 public:
73 wxAutoULong(ULONG value = 0) : m_Value(value) { }
74
75 operator ULONG&() { return m_Value; }
76 ULONG& operator=(ULONG value) { return m_Value = value; }
77
78 private:
79 ULONG m_Value;
80 };
81
82 // declare the methods and the member variable containing reference count
83 // you must also define the ms_aIids array somewhere with BEGIN_IID_TABLE
84 // and friends (see below)
85
86 #define DECLARE_IUNKNOWN_METHODS \
87 public: \
88 STDMETHODIMP QueryInterface(REFIID, void **); \
89 STDMETHODIMP_(ULONG) AddRef(); \
90 STDMETHODIMP_(ULONG) Release(); \
91 private: \
92 static const IID *ms_aIids[]; \
93 wxAutoULong m_cRef
94
95 // macros for declaring supported interfaces
96 // NB: you should write ADD_INTERFACE(Foo) and not ADD_INTERFACE(IID_IFoo)!
97 #define BEGIN_IID_TABLE(cname) const IID *cname::ms_aIids[] = {
98 #define ADD_IID(iid) &IID_I##iid,
99 #define END_IID_TABLE }
100
101 // implementation is as straightforward as possible
102 // Parameter: classname - the name of the class
103 #define IMPLEMENT_IUNKNOWN_METHODS(classname) \
104 STDMETHODIMP classname::QueryInterface(REFIID riid, void **ppv) \
105 { \
106 wxLogQueryInterface(_T(#classname), riid); \
107 \
108 if ( IsIidFromList(riid, ms_aIids, WXSIZEOF(ms_aIids)) ) { \
109 *ppv = this; \
110 AddRef(); \
111 \
112 return S_OK; \
113 } \
114 else { \
115 *ppv = NULL; \
116 \
117 return (HRESULT) E_NOINTERFACE; \
118 } \
119 } \
120 \
121 STDMETHODIMP_(ULONG) classname::AddRef() \
122 { \
123 wxLogAddRef(_T(#classname), m_cRef); \
124 \
125 return ++m_cRef; \
126 } \
127 \
128 STDMETHODIMP_(ULONG) classname::Release() \
129 { \
130 wxLogRelease(_T(#classname), m_cRef); \
131 \
132 if ( --m_cRef == 0 ) { \
133 delete this; \
134 return 0; \
135 } \
136 else \
137 return m_cRef; \
138 }
139
140 // ============================================================================
141 // Debugging support
142 // ============================================================================
143
144 // VZ: I don't know it's not done for compilers other than VC++ but I leave it
145 // as is. Please note, though, that tracing OLE interface calls may be
146 // incredibly useful when debugging OLE programs.
147 #if defined(__WXDEBUG__) && ( ( defined(__VISUALC__) && (__VISUALC__ >= 1000) ) || defined(__MWERKS__) )
148 // ----------------------------------------------------------------------------
149 // All OLE specific log functions have DebugTrace level (as LogTrace)
150 // ----------------------------------------------------------------------------
151
152 // tries to translate riid into a symbolic name, if possible
153 void wxLogQueryInterface(const wxChar *szInterface, REFIID riid);
154
155 // these functions print out the new value of reference counter
156 void wxLogAddRef (const wxChar *szInterface, ULONG cRef);
157 void wxLogRelease(const wxChar *szInterface, ULONG cRef);
158
159 #else //!WXDEBUG
160 #define wxLogQueryInterface(szInterface, riid)
161 #define wxLogAddRef(szInterface, cRef)
162 #define wxLogRelease(szInterface, cRef)
163 #endif //WXDEBUG
164
165 #endif //_WX_OLEUTILS_H
166