summaryrefslogtreecommitdiff
path: root/base/win/scoped_comptr.h
blob: 9442672054a90f99a47d49831ad197986bbbacd7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef BASE_WIN_SCOPED_COMPTR_H_
#define BASE_WIN_SCOPED_COMPTR_H_

#include <unknwn.h>

#include "base/logging.h"
#include "base/memory/ref_counted.h"

namespace base {
namespace win {

// A fairly minimalistic smart class for COM interface pointers.
// Uses scoped_refptr for the basic smart pointer functionality
// and adds a few IUnknown specific services.
template <class Interface, const IID* interface_id = &__uuidof(Interface)>
class ScopedComPtr : public scoped_refptr<Interface> {
 public:
  // Utility template to prevent users of ScopedComPtr from calling AddRef
  // and/or Release() without going through the ScopedComPtr class.
  class BlockIUnknownMethods : public Interface {
   private:
    STDMETHOD(QueryInterface)(REFIID iid, void** object) = 0;
    STDMETHOD_(ULONG, AddRef)() = 0;
    STDMETHOD_(ULONG, Release)() = 0;
  };

  typedef scoped_refptr<Interface> ParentClass;

  ScopedComPtr() {
  }

  explicit ScopedComPtr(Interface* p) : ParentClass(p) {
  }

  ScopedComPtr(const ScopedComPtr<Interface, interface_id>& p)
      : ParentClass(p) {
  }

  ~ScopedComPtr() {
    // We don't want the smart pointer class to be bigger than the pointer
    // it wraps.
    static_assert(
        sizeof(ScopedComPtr<Interface, interface_id>) == sizeof(Interface*),
        "ScopedComPtrSize");
  }

  // Explicit Release() of the held object.  Useful for reuse of the
  // ScopedComPtr instance.
  // Note that this function equates to IUnknown::Release and should not
  // be confused with e.g. unique_ptr::release().
  void Release() {
    if (this->ptr_ != NULL) {
      this->ptr_->Release();
      this->ptr_ = NULL;
    }
  }

  // Sets the internal pointer to NULL and returns the held object without
  // releasing the reference.
  Interface* Detach() {
    Interface* p = this->ptr_;
    this->ptr_ = NULL;
    return p;
  }

  // Accepts an interface pointer that has already been addref-ed.
  void Attach(Interface* p) {
    DCHECK(!this->ptr_);
    this->ptr_ = p;
  }

  // Retrieves the pointer address.
  // Used to receive object pointers as out arguments (and take ownership).
  // The function DCHECKs on the current value being NULL.
  // Usage: Foo(p.Receive());
  Interface** Receive() {
    DCHECK(!this->ptr_) << "Object leak. Pointer must be NULL";
    return &this->ptr_;
  }

  // A convenience for whenever a void pointer is needed as an out argument.
  void** ReceiveVoid() {
    return reinterpret_cast<void**>(Receive());
  }

  template <class Query>
  HRESULT QueryInterface(Query** p) {
    DCHECK(p != NULL);
    DCHECK(this->ptr_ != NULL);
    // IUnknown already has a template version of QueryInterface
    // so the iid parameter is implicit here. The only thing this
    // function adds are the DCHECKs.
    return this->ptr_->QueryInterface(p);
  }

  // QI for times when the IID is not associated with the type.
  HRESULT QueryInterface(const IID& iid, void** obj) {
    DCHECK(obj != NULL);
    DCHECK(this->ptr_ != NULL);
    return this->ptr_->QueryInterface(iid, obj);
  }

  // Queries |other| for the interface this object wraps and returns the
  // error code from the other->QueryInterface operation.
  HRESULT QueryFrom(IUnknown* object) {
    DCHECK(object != NULL);
    return object->QueryInterface(Receive());
  }

  // Convenience wrapper around CoCreateInstance
  HRESULT CreateInstance(const CLSID& clsid, IUnknown* outer = NULL,
                         DWORD context = CLSCTX_ALL) {
    DCHECK(!this->ptr_);
    HRESULT hr = ::CoCreateInstance(clsid, outer, context, *interface_id,
                                    reinterpret_cast<void**>(&this->ptr_));
    return hr;
  }

  // Checks if the identity of |other| and this object is the same.
  bool IsSameObject(IUnknown* other) {
    if (!other && !this->ptr_)
      return true;

    if (!other || !this->ptr_)
      return false;

    ScopedComPtr<IUnknown> my_identity;
    QueryInterface(my_identity.Receive());

    ScopedComPtr<IUnknown> other_identity;
    other->QueryInterface(other_identity.Receive());

    return my_identity == other_identity;
  }

  // Provides direct access to the interface.
  // Here we use a well known trick to make sure we block access to
  // IUnknown methods so that something bad like this doesn't happen:
  //    ScopedComPtr<IUnknown> p(Foo());
  //    p->Release();
  //    ... later the destructor runs, which will Release() again.
  // and to get the benefit of the DCHECKs we add to QueryInterface.
  // There's still a way to call these methods if you absolutely must
  // by statically casting the ScopedComPtr instance to the wrapped interface
  // and then making the call... but generally that shouldn't be necessary.
  BlockIUnknownMethods* operator->() const {
    DCHECK(this->ptr_ != NULL);
    return reinterpret_cast<BlockIUnknownMethods*>(this->ptr_);
  }

  // Pull in operator=() from the parent class.
  using scoped_refptr<Interface>::operator=;

  // static methods

  static const IID& iid() {
    return *interface_id;
  }
};

}  // namespace win
}  // namespace base

#endif  // BASE_WIN_SCOPED_COMPTR_H_