1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        wx/msw/private/comptr.h
3 // Purpose:     Smart pointer for COM interfaces.
4 // Author:      PB
5 // Created:     2012-04-16
6 // Copyright:   (c) 2012 wxWidgets team
7 // Licence:     wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
9 
10 #ifndef _WX_MSW_PRIVATE_COMPTR_H_
11 #define _WX_MSW_PRIVATE_COMPTR_H_
12 
13 // ----------------------------------------------------------------------------
14 // wxCOMPtr: A minimalistic smart pointer for use with COM interfaces.
15 // ----------------------------------------------------------------------------
16 
17 template <class T>
18 class wxCOMPtr
19 {
20 public:
21     typedef T element_type;
22 
wxCOMPtr()23     wxCOMPtr()
24         : m_ptr(NULL)
25     {
26     }
27 
wxCOMPtr(T * ptr)28     wxEXPLICIT wxCOMPtr(T* ptr)
29         : m_ptr(ptr)
30     {
31         if ( m_ptr )
32             m_ptr->AddRef();
33     }
34 
wxCOMPtr(const wxCOMPtr & ptr)35     wxCOMPtr(const wxCOMPtr& ptr)
36         : m_ptr(ptr.get())
37     {
38         if ( m_ptr )
39             m_ptr->AddRef();
40     }
41 
~wxCOMPtr()42     ~wxCOMPtr()
43     {
44         if ( m_ptr )
45             m_ptr->Release();
46     }
47 
48     void reset(T* ptr = NULL)
49     {
50         if ( m_ptr != ptr)
51         {
52             if ( ptr )
53                 ptr->AddRef();
54             if ( m_ptr )
55                 m_ptr->Release();
56             m_ptr = ptr;
57         }
58     }
59 
60     wxCOMPtr& operator=(const wxCOMPtr& ptr)
61     {
62         reset(ptr.get());
63         return *this;
64     }
65 
66     wxCOMPtr& operator=(T* ptr)
67     {
68         reset(ptr);
69         return *this;
70     }
71 
72     operator T*() const
73     {
74         return m_ptr;
75     }
76 
77     T& operator*() const
78     {
79         return *m_ptr;
80     }
81 
82     T* operator->() const
83     {
84         return m_ptr;
85     }
86 
87     // It would be better to forbid direct access completely but we do need
88     // for QueryInterface() and similar functions, so provide it but it can
89     // only be used to initialize the pointer, not to modify an existing one.
90     T** operator&()
91     {
92         wxASSERT_MSG(!m_ptr,
93                      wxS("Can't get direct access to initialized pointer"));
94 
95         return &m_ptr;
96     }
97 
get()98     T* get() const
99     {
100         return m_ptr;
101     }
102 
103     bool operator<(T* ptr) const
104     {
105         return get() < ptr;
106     }
107 
108 private:
109     T* m_ptr;
110 };
111 
112 // Define a helper for the macro below: we just need a function taking a
113 // pointer and not returning anything to avoid warnings about unused return
114 // value of the cast in the macro itself.
PPV_ARGS_CHECK(void *)115 namespace wxPrivate { inline void PPV_ARGS_CHECK(void*) { } }
116 
117 // Takes the interface name and a pointer to a pointer of the interface type
118 // and expands into the IID of this interface and the same pointer but after a
119 // type-safety check.
120 //
121 // This is similar to the standard IID_PPV_ARGS macro but takes the pointer
122 // type instead of relying on the non-standard Microsoft __uuidof().
123 #define wxIID_PPV_ARGS(IType, pType) \
124     IID_##IType, \
125     (wxPrivate::PPV_ARGS_CHECK(static_cast<IType*>(*pType)), \
126      reinterpret_cast<void**>(pType))
127 
128 #endif // _WX_MSW_PRIVATE_COMPTR_H_
129 
130