1 // Copyright (c) 2006-2008 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_SCOPED_COMPTR_WIN_H_
6 #define BASE_SCOPED_COMPTR_WIN_H_
10 #include "base/logging.h"
11 #include "base/ref_counted.h"
13 // Utility template to prevent users of ScopedComPtr from calling AddRef and/or
14 // Release() without going through the ScopedComPtr class.
15 template <class Interface
>
16 class BlockIUnknownMethods
: public Interface
{
18 STDMETHOD(QueryInterface
)(REFIID iid
, void** object
) = 0;
19 STDMETHOD_(ULONG
, AddRef
)() = 0;
20 STDMETHOD_(ULONG
, Release
)() = 0;
23 // A fairly minimalistic smart class for COM interface pointers.
24 // Uses scoped_refptr for the basic smart pointer functionality
25 // and adds a few IUnknown specific services.
26 template <class Interface
, const IID
* interface_id
= &__uuidof(Interface
)>
27 class ScopedComPtr
: public scoped_refptr
<Interface
> {
29 typedef scoped_refptr
<Interface
> ParentClass
;
34 explicit ScopedComPtr(Interface
* p
) : ParentClass(p
) {
37 ScopedComPtr(const ScopedComPtr
<Interface
, interface_id
>& p
)
42 // We don't want the smart pointer class to be bigger than the pointer
44 COMPILE_ASSERT(sizeof(ScopedComPtr
<Interface
, interface_id
>) ==
45 sizeof(Interface
*), ScopedComPtrSize
);
48 // Explicit Release() of the held object. Useful for reuse of the
49 // ScopedComPtr instance.
50 // Note that this function equates to IUnknown::Release and should not
51 // be confused with e.g. scoped_ptr::release().
59 // Sets the internal pointer to NULL and returns the held object without
60 // releasing the reference.
67 // Accepts an interface pointer that has already been addref-ed.
68 void Attach(Interface
* p
) {
73 // Retrieves the pointer address.
74 // Used to receive object pointers as out arguments (and take ownership).
75 // The function DCHECKs on the current value being NULL.
76 // Usage: Foo(p.Receive());
77 Interface
** Receive() {
78 DCHECK(ptr_
== NULL
) << "Object leak. Pointer must be NULL";
82 template <class Query
>
83 HRESULT
QueryInterface(Query
** p
) {
86 // IUnknown already has a template version of QueryInterface
87 // so the iid parameter is implicit here. The only thing this
88 // function adds are the DCHECKs.
89 return ptr_
->QueryInterface(p
);
92 // QI for times when the IID is not associated with the type.
93 HRESULT
QueryInterface(const IID
& iid
, void** obj
) {
96 return ptr_
->QueryInterface(iid
, obj
);
99 // Queries |other| for the interface this object wraps and returns the
100 // error code from the other->QueryInterface operation.
101 HRESULT
QueryFrom(IUnknown
* object
) {
102 DCHECK(object
!= NULL
);
103 return object
->QueryInterface(Receive());
106 // Convenience wrapper around CoCreateInstance
107 HRESULT
CreateInstance(const CLSID
& clsid
, IUnknown
* outer
= NULL
,
108 DWORD context
= CLSCTX_ALL
) {
109 DCHECK(ptr_
== NULL
);
110 HRESULT hr
= ::CoCreateInstance(clsid
, outer
, context
, *interface_id
,
111 reinterpret_cast<void**>(&ptr_
));
115 // Checks if the identity of |other| and this object is the same.
116 bool IsSameObject(IUnknown
* other
) {
123 ScopedComPtr
<IUnknown
> my_identity
;
124 QueryInterface(my_identity
.Receive());
126 ScopedComPtr
<IUnknown
> other_identity
;
127 other
->QueryInterface(other_identity
.Receive());
129 return static_cast<IUnknown
*>(my_identity
) ==
130 static_cast<IUnknown
*>(other_identity
);
133 // Provides direct access to the interface.
134 // Here we use a well known trick to make sure we block access to
135 // IUknown methods so that something bad like this doesn't happen:
136 // ScopedComPtr<IUnknown> p(Foo());
138 // ... later the destructor runs, which will Release() again.
139 // and to get the benefit of the DCHECKs we add to QueryInterface.
140 // There's still a way to call these methods if you absolutely must
141 // by statically casting the ScopedComPtr instance to the wrapped interface
142 // and then making the call... but generally that shouldn't be necessary.
143 BlockIUnknownMethods
<Interface
>* operator->() const {
144 DCHECK(ptr_
!= NULL
);
145 return reinterpret_cast<BlockIUnknownMethods
<Interface
>*>(ptr_
);
148 // Pull in operator=() from the parent class.
149 using scoped_refptr
<Interface
>::operator=;
153 static const IID
& iid() {
154 return *interface_id
;
158 #endif // BASE_SCOPED_COMPTR_WIN_H_