Home | History | Annotate | Download | only in win
      1 /*
      2  * Copyright (C) 2007, 2010 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #ifndef COMPtr_h
     27 #define COMPtr_h
     28 
     29 #ifndef NOMINMAX
     30 #define NOMINMAX
     31 #endif
     32 
     33 #include <unknwn.h>
     34 #include <wtf/Assertions.h>
     35 #include <wtf/HashTraits.h>
     36 
     37 #if !OS(WINCE)
     38 #include <guiddef.h>
     39 #endif
     40 
     41 typedef long HRESULT;
     42 
     43 // FIXME: Should we put this into the WebCore namespace and use "using" on it
     44 // as we do with things in WTF?
     45 
     46 enum AdoptCOMTag { AdoptCOM };
     47 enum QueryTag { Query };
     48 enum CreateTag { Create };
     49 
     50 template<typename T> class COMPtr {
     51 public:
     52     COMPtr() : m_ptr(0) { }
     53     COMPtr(T* ptr) : m_ptr(ptr) { if (m_ptr) m_ptr->AddRef(); }
     54     COMPtr(AdoptCOMTag, T* ptr) : m_ptr(ptr) { }
     55     COMPtr(const COMPtr& o) : m_ptr(o.m_ptr) { if (T* ptr = m_ptr) ptr->AddRef(); }
     56 
     57     COMPtr(QueryTag, IUnknown* ptr) : m_ptr(copyQueryInterfaceRef(ptr)) { }
     58     template<typename U> COMPtr(QueryTag, const COMPtr<U>& ptr) : m_ptr(copyQueryInterfaceRef(ptr.get())) { }
     59 
     60     COMPtr(CreateTag, const IID& clsid) : m_ptr(createInstance(clsid)) { }
     61 
     62     // Hash table deleted values, which are only constructed and never copied or destroyed.
     63     COMPtr(WTF::HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
     64     bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
     65 
     66     ~COMPtr() { if (m_ptr) m_ptr->Release(); }
     67 
     68     T* get() const { return m_ptr; }
     69 
     70     void clear();
     71     T* leakRef();
     72 
     73     T& operator*() const { return *m_ptr; }
     74     T* operator->() const { return m_ptr; }
     75 
     76     T** operator&() { ASSERT(!m_ptr); return &m_ptr; }
     77 
     78     bool operator!() const { return !m_ptr; }
     79 
     80     // This conversion operator allows implicit conversion to bool but not to other integer types.
     81     typedef T* (COMPtr::*UnspecifiedBoolType)() const;
     82     operator UnspecifiedBoolType() const { return m_ptr ? &COMPtr::get : 0; }
     83 
     84     COMPtr& operator=(const COMPtr&);
     85     COMPtr& operator=(T*);
     86     template<typename U> COMPtr& operator=(const COMPtr<U>&);
     87 
     88     void query(IUnknown* ptr) { adoptRef(copyQueryInterfaceRef(ptr)); }
     89     template<typename U> void query(const COMPtr<U>& ptr) { query(ptr.get()); }
     90 
     91     void create(const IID& clsid) { adoptRef(createInstance(clsid)); }
     92 
     93     template<typename U> HRESULT copyRefTo(U**);
     94     void adoptRef(T*);
     95 
     96     // FIXME: Remove releaseRef once we change all callers to call leakRef instead.
     97     T* releaseRef() { return leakRef(); }
     98 
     99 private:
    100     static T* copyQueryInterfaceRef(IUnknown*);
    101     static T* createInstance(const IID& clsid);
    102     static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); }
    103 
    104     T* m_ptr;
    105 };
    106 
    107 template<typename T> inline void COMPtr<T>::clear()
    108 {
    109     if (T* ptr = m_ptr) {
    110         m_ptr = 0;
    111         ptr->Release();
    112     }
    113 }
    114 
    115 template<typename T> inline T* COMPtr<T>::leakRef()
    116 {
    117     T* ptr = m_ptr;
    118     m_ptr = 0;
    119     return ptr;
    120 }
    121 
    122 template<typename T> inline T* COMPtr<T>::createInstance(const IID& clsid)
    123 {
    124     T* result;
    125     if (FAILED(CoCreateInstance(clsid, 0, CLSCTX_ALL, __uuidof(result), reinterpret_cast<void**>(&result))))
    126         return 0;
    127     return result;
    128 }
    129 
    130 template<typename T> inline T* COMPtr<T>::copyQueryInterfaceRef(IUnknown* ptr)
    131 {
    132     if (!ptr)
    133         return 0;
    134     T* result;
    135     if (FAILED(ptr->QueryInterface(&result)))
    136         return 0;
    137     return result;
    138 }
    139 
    140 template<typename T> template<typename U> inline HRESULT COMPtr<T>::copyRefTo(U** ptr)
    141 {
    142     if (!ptr)
    143         return E_POINTER;
    144     *ptr = m_ptr;
    145     if (m_ptr)
    146         m_ptr->AddRef();
    147     return S_OK;
    148 }
    149 
    150 template<typename T> inline void COMPtr<T>::adoptRef(T *ptr)
    151 {
    152     if (m_ptr)
    153         m_ptr->Release();
    154     m_ptr = ptr;
    155 }
    156 
    157 template<typename T> inline COMPtr<T>& COMPtr<T>::operator=(const COMPtr<T>& o)
    158 {
    159     T* optr = o.get();
    160     if (optr)
    161         optr->AddRef();
    162     T* ptr = m_ptr;
    163     m_ptr = optr;
    164     if (ptr)
    165         ptr->Release();
    166     return *this;
    167 }
    168 
    169 template<typename T> template<typename U> inline COMPtr<T>& COMPtr<T>::operator=(const COMPtr<U>& o)
    170 {
    171     T* optr = o.get();
    172     if (optr)
    173         optr->AddRef();
    174     T* ptr = m_ptr;
    175     m_ptr = optr;
    176     if (ptr)
    177         ptr->Release();
    178     return *this;
    179 }
    180 
    181 template<typename T> inline COMPtr<T>& COMPtr<T>::operator=(T* optr)
    182 {
    183     if (optr)
    184         optr->AddRef();
    185     T* ptr = m_ptr;
    186     m_ptr = optr;
    187     if (ptr)
    188         ptr->Release();
    189     return *this;
    190 }
    191 
    192 template<typename T, typename U> inline bool operator==(const COMPtr<T>& a, const COMPtr<U>& b)
    193 {
    194     return a.get() == b.get();
    195 }
    196 
    197 template<typename T, typename U> inline bool operator==(const COMPtr<T>& a, U* b)
    198 {
    199     return a.get() == b;
    200 }
    201 
    202 template<typename T, typename U> inline bool operator==(T* a, const COMPtr<U>& b)
    203 {
    204     return a == b.get();
    205 }
    206 
    207 template<typename T, typename U> inline bool operator!=(const COMPtr<T>& a, const COMPtr<U>& b)
    208 {
    209     return a.get() != b.get();
    210 }
    211 
    212 template<typename T, typename U> inline bool operator!=(const COMPtr<T>& a, U* b)
    213 {
    214     return a.get() != b;
    215 }
    216 
    217 template<typename T, typename U> inline bool operator!=(T* a, const COMPtr<U>& b)
    218 {
    219     return a != b.get();
    220 }
    221 
    222 namespace WTF {
    223 
    224     template<typename P> struct HashTraits<COMPtr<P> > : GenericHashTraits<COMPtr<P> > {
    225         static const bool emptyValueIsZero = true;
    226         static void constructDeletedValue(COMPtr<P>& slot) { new (&slot) COMPtr<P>(HashTableDeletedValue); }
    227         static bool isDeletedValue(const COMPtr<P>& value) { return value.isHashTableDeletedValue(); }
    228     };
    229 
    230     template<typename P> struct PtrHash<COMPtr<P> > : PtrHash<P*> {
    231         using PtrHash<P*>::hash;
    232         static unsigned hash(const COMPtr<P>& key) { return hash(key.get()); }
    233         using PtrHash<P*>::equal;
    234         static bool equal(const COMPtr<P>& a, const COMPtr<P>& b) { return a == b; }
    235         static bool equal(P* a, const COMPtr<P>& b) { return a == b; }
    236         static bool equal(const COMPtr<P>& a, P* b) { return a == b; }
    237     };
    238 
    239     template<typename P> struct DefaultHash<COMPtr<P> > { typedef PtrHash<COMPtr<P> > Hash; };
    240 }
    241 
    242 #endif
    243