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