From f5f36152e843a215629f3991da644f8da37e02ff Mon Sep 17 00:00:00 2001 From: "tommi@chromium.org" Date: Thu, 15 Jan 2009 17:16:48 +0000 Subject: Renaming the following files to include the _win suffix: scoped_comptr*.* scoped_bstr*.* addition: time_unittest_win.cc -> time_win_unittest.cc BUG=6409 Also renaming the scoped_comptr class to ScopedComPtr to conform with chromium style (and not boost as before). Review URL: http://codereview.chromium.org/18054 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8098 0039d316-1c4b-4281-b951-d872f2087c98 --- base/scoped_comptr_win.h | 148 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 base/scoped_comptr_win.h (limited to 'base/scoped_comptr_win.h') diff --git a/base/scoped_comptr_win.h b/base/scoped_comptr_win.h new file mode 100644 index 0000000..8f677a0 --- /dev/null +++ b/base/scoped_comptr_win.h @@ -0,0 +1,148 @@ +// Copyright (c) 2006-2008 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_SCOPED_COMPTR_WIN_H_ +#define BASE_SCOPED_COMPTR_WIN_H_ + +#include + +#include "base/logging.h" +#include "base/ref_counted.h" + +// Utility template to prevent users of ScopedComPtr from calling AddRef and/or +// Release() without going through the ScopedComPtr class. +template +class BlockIUnknownMethods : public Interface { + private: + STDMETHOD(QueryInterface)(REFIID iid, void** object) = 0; + STDMETHOD_(ULONG, AddRef)() = 0; + STDMETHOD_(ULONG, Release)() = 0; +}; + +// 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 ScopedComPtr : public scoped_refptr { + public: + typedef scoped_refptr ParentClass; + + ScopedComPtr() { + } + + explicit ScopedComPtr(Interface* p) : ParentClass(p) { + } + + explicit ScopedComPtr(const ScopedComPtr& p) + : ParentClass(p) { + } + + ~ScopedComPtr() { + // We don't want the smart pointer class to be bigger than the pointer + // it wraps. + COMPILE_ASSERT(sizeof(ScopedComPtr) == + 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. scoped_ptr::release(). + void Release() { + if (ptr_ != NULL) { + ptr_->Release(); + ptr_ = NULL; + } + } + + // Sets the internal pointer to NULL and returns the held object without + // releasing the reference. + Interface* Detach() { + Interface* p = ptr_; + ptr_ = NULL; + return p; + } + + // Accepts an interface pointer that has already been addref-ed. + void Attach(Interface* p) { + DCHECK(ptr_ == NULL); + 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(ptr_ == NULL) << "Object leak. Pointer must be NULL"; + return &ptr_; + } + + template + HRESULT QueryInterface(Query** p) { + DCHECK(p != NULL); + DCHECK(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 ptr_->QueryInterface(p); + } + + // 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(ptr_ == NULL); + HRESULT hr = ::CoCreateInstance(clsid, outer, context, *interface_id, + reinterpret_cast(&ptr_)); + return hr; + } + + // Checks if the identity of |other| and this object is the same. + bool IsSameObject(IUnknown* other) { + if (!other && !ptr_) + return true; + + if (!other || !ptr_) + return false; + + ScopedComPtr my_identity; + QueryInterface(my_identity.Receive()); + + ScopedComPtr other_identity; + other->QueryInterface(other_identity.Receive()); + + return static_cast(my_identity) == + static_cast(other_identity); + } + + // Provides direct access to the interface. + // Here we use a well known trick to make sure we block access to + // IUknown methods so that something bad like this doesn't happen: + // ScopedComPtr 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(ptr_ != NULL); + return reinterpret_cast*>(ptr_); + } + + // static methods + + static const IID& iid() { + return *interface_id; + } +}; + +#endif // BASE_SCOPED_COMPTR_WIN_H_ -- cgit v1.1