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_
10 #include "base/logging.h"
11 #include "base/memory/ref_counted.h"
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
> {
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
{
26 STDMETHOD(QueryInterface
)(REFIID iid
, void** object
) = 0;
27 STDMETHOD_(ULONG
, AddRef
)() = 0;
28 STDMETHOD_(ULONG
, Release
)() = 0;
31 typedef scoped_refptr
<Interface
> ParentClass
;
36 explicit ScopedComPtr(Interface
* p
) : ParentClass(p
) {
39 ScopedComPtr(const ScopedComPtr
<Interface
, interface_id
>& p
)
44 // We don't want the smart pointer class to be bigger than the pointer
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().
55 if (this->ptr_
!= NULL
) {
56 this->ptr_
->Release();
61 // Sets the internal pointer to NULL and returns the held object without
62 // releasing the reference.
64 Interface
* p
= this->ptr_
;
69 // Accepts an interface pointer that has already been addref-ed.
70 void Attach(Interface
* 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";
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
) {
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
) {
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
) {
117 HRESULT hr
= ::CoCreateInstance(clsid
, outer
, context
, *interface_id
,
118 reinterpret_cast<void**>(&this->ptr_
));
122 // Checks if the identity of |other| and this object is the same.
123 bool IsSameObject(IUnknown
* other
) {
124 if (!other
&& !this->ptr_
)
127 if (!other
|| !this->ptr_
)
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());
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=;
159 static const IID
& iid() {
160 return *interface_id
;
167 #endif // BASE_WIN_SCOPED_COMPTR_H_