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