| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef BASE_SCOPED_COMPTR_WIN_H_ | 5 // TODO(brettw) remove this file when all callers are converted to using the |
| 6 #define BASE_SCOPED_COMPTR_WIN_H_ | 6 // new location/namespace |
| 7 #pragma once | 7 #include "base/win/scoped_comptr.h" |
| 8 | 8 |
| 9 #include <unknwn.h> | 9 using base::win::ScopedComPtr; |
| 10 | |
| 11 #include "base/logging.h" | |
| 12 #include "base/ref_counted.h" | |
| 13 | |
| 14 // Utility template to prevent users of ScopedComPtr from calling AddRef and/or | |
| 15 // Release() without going through the ScopedComPtr class. | |
| 16 template <class Interface> | |
| 17 class BlockIUnknownMethods : public Interface { | |
| 18 private: | |
| 19 STDMETHOD(QueryInterface)(REFIID iid, void** object) = 0; | |
| 20 STDMETHOD_(ULONG, AddRef)() = 0; | |
| 21 STDMETHOD_(ULONG, Release)() = 0; | |
| 22 }; | |
| 23 | |
| 24 // A fairly minimalistic smart class for COM interface pointers. | |
| 25 // Uses scoped_refptr for the basic smart pointer functionality | |
| 26 // and adds a few IUnknown specific services. | |
| 27 template <class Interface, const IID* interface_id = &__uuidof(Interface)> | |
| 28 class ScopedComPtr : public scoped_refptr<Interface> { | |
| 29 public: | |
| 30 typedef scoped_refptr<Interface> ParentClass; | |
| 31 | |
| 32 ScopedComPtr() { | |
| 33 } | |
| 34 | |
| 35 explicit ScopedComPtr(Interface* p) : ParentClass(p) { | |
| 36 } | |
| 37 | |
| 38 ScopedComPtr(const ScopedComPtr<Interface, interface_id>& p) | |
| 39 : ParentClass(p) { | |
| 40 } | |
| 41 | |
| 42 ~ScopedComPtr() { | |
| 43 // We don't want the smart pointer class to be bigger than the pointer | |
| 44 // it wraps. | |
| 45 COMPILE_ASSERT(sizeof(ScopedComPtr<Interface, interface_id>) == | |
| 46 sizeof(Interface*), ScopedComPtrSize); | |
| 47 } | |
| 48 | |
| 49 // Explicit Release() of the held object. Useful for reuse of the | |
| 50 // ScopedComPtr instance. | |
| 51 // Note that this function equates to IUnknown::Release and should not | |
| 52 // be confused with e.g. scoped_ptr::release(). | |
| 53 void Release() { | |
| 54 if (ptr_ != NULL) { | |
| 55 ptr_->Release(); | |
| 56 ptr_ = NULL; | |
| 57 } | |
| 58 } | |
| 59 | |
| 60 // Sets the internal pointer to NULL and returns the held object without | |
| 61 // releasing the reference. | |
| 62 Interface* Detach() { | |
| 63 Interface* p = ptr_; | |
| 64 ptr_ = NULL; | |
| 65 return p; | |
| 66 } | |
| 67 | |
| 68 // Accepts an interface pointer that has already been addref-ed. | |
| 69 void Attach(Interface* p) { | |
| 70 DCHECK(ptr_ == NULL); | |
| 71 ptr_ = p; | |
| 72 } | |
| 73 | |
| 74 // Retrieves the pointer address. | |
| 75 // Used to receive object pointers as out arguments (and take ownership). | |
| 76 // The function DCHECKs on the current value being NULL. | |
| 77 // Usage: Foo(p.Receive()); | |
| 78 Interface** Receive() { | |
| 79 DCHECK(ptr_ == NULL) << "Object leak. Pointer must be NULL"; | |
| 80 return &ptr_; | |
| 81 } | |
| 82 | |
| 83 template <class Query> | |
| 84 HRESULT QueryInterface(Query** p) { | |
| 85 DCHECK(p != NULL); | |
| 86 DCHECK(ptr_ != NULL); | |
| 87 // IUnknown already has a template version of QueryInterface | |
| 88 // so the iid parameter is implicit here. The only thing this | |
| 89 // function adds are the DCHECKs. | |
| 90 return ptr_->QueryInterface(p); | |
| 91 } | |
| 92 | |
| 93 // QI for times when the IID is not associated with the type. | |
| 94 HRESULT QueryInterface(const IID& iid, void** obj) { | |
| 95 DCHECK(obj != NULL); | |
| 96 DCHECK(ptr_ != NULL); | |
| 97 return ptr_->QueryInterface(iid, obj); | |
| 98 } | |
| 99 | |
| 100 // Queries |other| for the interface this object wraps and returns the | |
| 101 // error code from the other->QueryInterface operation. | |
| 102 HRESULT QueryFrom(IUnknown* object) { | |
| 103 DCHECK(object != NULL); | |
| 104 return object->QueryInterface(Receive()); | |
| 105 } | |
| 106 | |
| 107 // Convenience wrapper around CoCreateInstance | |
| 108 HRESULT CreateInstance(const CLSID& clsid, IUnknown* outer = NULL, | |
| 109 DWORD context = CLSCTX_ALL) { | |
| 110 DCHECK(ptr_ == NULL); | |
| 111 HRESULT hr = ::CoCreateInstance(clsid, outer, context, *interface_id, | |
| 112 reinterpret_cast<void**>(&ptr_)); | |
| 113 return hr; | |
| 114 } | |
| 115 | |
| 116 // Checks if the identity of |other| and this object is the same. | |
| 117 bool IsSameObject(IUnknown* other) { | |
| 118 if (!other && !ptr_) | |
| 119 return true; | |
| 120 | |
| 121 if (!other || !ptr_) | |
| 122 return false; | |
| 123 | |
| 124 ScopedComPtr<IUnknown> my_identity; | |
| 125 QueryInterface(my_identity.Receive()); | |
| 126 | |
| 127 ScopedComPtr<IUnknown> other_identity; | |
| 128 other->QueryInterface(other_identity.Receive()); | |
| 129 | |
| 130 return static_cast<IUnknown*>(my_identity) == | |
| 131 static_cast<IUnknown*>(other_identity); | |
| 132 } | |
| 133 | |
| 134 // Provides direct access to the interface. | |
| 135 // Here we use a well known trick to make sure we block access to | |
| 136 // IUknown methods so that something bad like this doesn't happen: | |
| 137 // ScopedComPtr<IUnknown> p(Foo()); | |
| 138 // p->Release(); | |
| 139 // ... later the destructor runs, which will Release() again. | |
| 140 // and to get the benefit of the DCHECKs we add to QueryInterface. | |
| 141 // There's still a way to call these methods if you absolutely must | |
| 142 // by statically casting the ScopedComPtr instance to the wrapped interface | |
| 143 // and then making the call... but generally that shouldn't be necessary. | |
| 144 BlockIUnknownMethods<Interface>* operator->() const { | |
| 145 DCHECK(ptr_ != NULL); | |
| 146 return reinterpret_cast<BlockIUnknownMethods<Interface>*>(ptr_); | |
| 147 } | |
| 148 | |
| 149 // Pull in operator=() from the parent class. | |
| 150 using scoped_refptr<Interface>::operator=; | |
| 151 | |
| 152 // static methods | |
| 153 | |
| 154 static const IID& iid() { | |
| 155 return *interface_id; | |
| 156 } | |
| 157 }; | |
| 158 | |
| 159 #endif // BASE_SCOPED_COMPTR_WIN_H_ | |
| OLD | NEW |