15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef BASE_WIN_SCOPED_HANDLE_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_WIN_SCOPED_HANDLE_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_export.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/move.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(rvargas): remove this with the rest of the verifier.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(COMPILER_MSVC)
184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <intrin.h>
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_WIN_GET_CALLER _ReturnAddress()
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(COMPILER_GCC)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_WIN_GET_CALLER __builtin_extract_return_addr(\\
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __builtin_return_address(0))
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace base {
264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace win {
274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Generic wrapper for raw handles that takes care of closing handles
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// automatically. The class interface follows the style of
30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// the ScopedFILE class with one addition:
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   - IsValid() method can tolerate multiple invalid handle values such as NULL
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     and INVALID_HANDLE_VALUE (-1) for Win32 handles.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class Traits, class Verifier>
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GenericScopedHandle {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MOVE_ONLY_TYPE_FOR_CPP_03(GenericScopedHandle, RValue)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef typename Traits::Handle Handle;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GenericScopedHandle() : handle_(Traits::NullHandle()) {}
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit GenericScopedHandle(Handle handle) : handle_(Traits::NullHandle()) {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Set(handle);
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Move constructor for C++03 move emulation of this type.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GenericScopedHandle(RValue other) : handle_(Traits::NullHandle()) {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Set(other.object->Take());
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~GenericScopedHandle() {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Close();
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool IsValid() const {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Traits::IsHandleValid(handle_);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Move operator= for C++03 move emulation of this type.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GenericScopedHandle& operator=(RValue other) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (this != other.object) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Set(other.object->Take());
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return *this;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Set(Handle handle) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (handle_ != handle) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Close();
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (Traits::IsHandleValid(handle)) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        handle_ = handle;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Verifier::StartTracking(handle, this, BASE_WIN_GET_CALLER,
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                tracked_objects::GetProgramCounter());
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Handle Get() const {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return handle_;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  operator Handle() const {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return handle_;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Transfers ownership away from this object.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Handle Take() {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Handle temp = handle_;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    handle_ = Traits::NullHandle();
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (Traits::IsHandleValid(temp)) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Verifier::StopTracking(temp, this, BASE_WIN_GET_CALLER,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             tracked_objects::GetProgramCounter());
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return temp;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Explicitly closes the owned handle.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Close() {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (Traits::IsHandleValid(handle_)) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Verifier::StopTracking(handle_, this, BASE_WIN_GET_CALLER,
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             tracked_objects::GetProgramCounter());
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      Traits::CloseHandle(handle_);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      handle_ = Traits::NullHandle();
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Handle handle_;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef BASE_WIN_GET_CALLER
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The traits class for Win32 handles that can be closed via CloseHandle() API.
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class HandleTraits {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef HANDLE Handle;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Closes the handle.
1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  static bool BASE_EXPORT CloseHandle(HANDLE handle);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if the handle value is valid.
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool IsHandleValid(HANDLE handle) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return handle != NULL && handle != INVALID_HANDLE_VALUE;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns NULL handle value.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static HANDLE NullHandle() {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_IMPLICIT_CONSTRUCTORS(HandleTraits);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Do-nothing verifier.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DummyVerifierTraits {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef HANDLE Handle;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void StartTracking(HANDLE handle, const void* owner,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const void* pc1, const void* pc2) {}
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void StopTracking(HANDLE handle, const void* owner,
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const void* pc1, const void* pc2) {}
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_IMPLICIT_CONSTRUCTORS(DummyVerifierTraits);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Performs actual run-time tracking.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BASE_EXPORT VerifierTraits {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef HANDLE Handle;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void StartTracking(HANDLE handle, const void* owner,
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const void* pc1, const void* pc2);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void StopTracking(HANDLE handle, const void* owner,
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const void* pc1, const void* pc2);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_IMPLICIT_CONSTRUCTORS(VerifierTraits);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef GenericScopedHandle<HandleTraits, VerifierTraits> ScopedHandle;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// This function may be called by the embedder to disable the use of
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// VerifierTraits at runtime. It has no effect if DummyVerifierTraits is used
1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// for ScopedHandle.
1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BASE_EXPORT DisableHandleVerifier();
1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// This should be called whenever the OS is closing a handle, if extended
1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// verification of improper handle closing is desired. If |handle| is being
1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// tracked by the handle verifier and ScopedHandle is not the one closing it,
1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// a CHECK is generated.
1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BASE_EXPORT OnHandleBeingClosed(HANDLE handle);
1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace win
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // BASE_SCOPED_HANDLE_WIN_H_
182