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