Home | History | Annotate | Download | only in win
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef BASE_WIN_SCOPED_HANDLE_H_
      6 #define BASE_WIN_SCOPED_HANDLE_H_
      7 
      8 #include <windows.h>
      9 
     10 #include "base/base_export.h"
     11 #include "base/basictypes.h"
     12 #include "base/location.h"
     13 #include "base/logging.h"
     14 #include "base/move.h"
     15 
     16 // TODO(rvargas): remove this with the rest of the verifier.
     17 #if defined(COMPILER_MSVC)
     18 #include <intrin.h>
     19 #define BASE_WIN_GET_CALLER _ReturnAddress()
     20 #elif defined(COMPILER_GCC)
     21 #define BASE_WIN_GET_CALLER __builtin_extract_return_addr(\\
     22     __builtin_return_address(0))
     23 #endif
     24 
     25 namespace base {
     26 namespace win {
     27 
     28 // Generic wrapper for raw handles that takes care of closing handles
     29 // automatically. The class interface follows the style of
     30 // the ScopedFILE class with one addition:
     31 //   - IsValid() method can tolerate multiple invalid handle values such as NULL
     32 //     and INVALID_HANDLE_VALUE (-1) for Win32 handles.
     33 template <class Traits, class Verifier>
     34 class GenericScopedHandle {
     35   MOVE_ONLY_TYPE_FOR_CPP_03(GenericScopedHandle, RValue)
     36 
     37  public:
     38   typedef typename Traits::Handle Handle;
     39 
     40   GenericScopedHandle() : handle_(Traits::NullHandle()) {}
     41 
     42   explicit GenericScopedHandle(Handle handle) : handle_(Traits::NullHandle()) {
     43     Set(handle);
     44   }
     45 
     46   // Move constructor for C++03 move emulation of this type.
     47   GenericScopedHandle(RValue other) : handle_(Traits::NullHandle()) {
     48     Set(other.object->Take());
     49   }
     50 
     51   ~GenericScopedHandle() {
     52     Close();
     53   }
     54 
     55   bool IsValid() const {
     56     return Traits::IsHandleValid(handle_);
     57   }
     58 
     59   // Move operator= for C++03 move emulation of this type.
     60   GenericScopedHandle& operator=(RValue other) {
     61     if (this != other.object) {
     62       Set(other.object->Take());
     63     }
     64     return *this;
     65   }
     66 
     67   void Set(Handle handle) {
     68     if (handle_ != handle) {
     69       Close();
     70 
     71       if (Traits::IsHandleValid(handle)) {
     72         handle_ = handle;
     73         Verifier::StartTracking(handle, this, BASE_WIN_GET_CALLER,
     74                                 tracked_objects::GetProgramCounter());
     75       }
     76     }
     77   }
     78 
     79   Handle Get() const {
     80     return handle_;
     81   }
     82 
     83   operator Handle() const {
     84     return handle_;
     85   }
     86 
     87   // Transfers ownership away from this object.
     88   Handle Take() {
     89     Handle temp = handle_;
     90     handle_ = Traits::NullHandle();
     91     if (Traits::IsHandleValid(temp)) {
     92       Verifier::StopTracking(temp, this, BASE_WIN_GET_CALLER,
     93                              tracked_objects::GetProgramCounter());
     94     }
     95     return temp;
     96   }
     97 
     98   // Explicitly closes the owned handle.
     99   void Close() {
    100     if (Traits::IsHandleValid(handle_)) {
    101       Verifier::StopTracking(handle_, this, BASE_WIN_GET_CALLER,
    102                              tracked_objects::GetProgramCounter());
    103 
    104       Traits::CloseHandle(handle_);
    105       handle_ = Traits::NullHandle();
    106     }
    107   }
    108 
    109  private:
    110   Handle handle_;
    111 };
    112 
    113 #undef BASE_WIN_GET_CALLER
    114 
    115 // The traits class for Win32 handles that can be closed via CloseHandle() API.
    116 class HandleTraits {
    117  public:
    118   typedef HANDLE Handle;
    119 
    120   // Closes the handle.
    121   static bool BASE_EXPORT CloseHandle(HANDLE handle);
    122 
    123   // Returns true if the handle value is valid.
    124   static bool IsHandleValid(HANDLE handle) {
    125     return handle != NULL && handle != INVALID_HANDLE_VALUE;
    126   }
    127 
    128   // Returns NULL handle value.
    129   static HANDLE NullHandle() {
    130     return NULL;
    131   }
    132 
    133  private:
    134   DISALLOW_IMPLICIT_CONSTRUCTORS(HandleTraits);
    135 };
    136 
    137 // Do-nothing verifier.
    138 class DummyVerifierTraits {
    139  public:
    140   typedef HANDLE Handle;
    141 
    142   static void StartTracking(HANDLE handle, const void* owner,
    143                             const void* pc1, const void* pc2) {}
    144   static void StopTracking(HANDLE handle, const void* owner,
    145                            const void* pc1, const void* pc2) {}
    146 
    147  private:
    148   DISALLOW_IMPLICIT_CONSTRUCTORS(DummyVerifierTraits);
    149 };
    150 
    151 // Performs actual run-time tracking.
    152 class BASE_EXPORT VerifierTraits {
    153  public:
    154   typedef HANDLE Handle;
    155 
    156   static void StartTracking(HANDLE handle, const void* owner,
    157                             const void* pc1, const void* pc2);
    158   static void StopTracking(HANDLE handle, const void* owner,
    159                            const void* pc1, const void* pc2);
    160 
    161  private:
    162   DISALLOW_IMPLICIT_CONSTRUCTORS(VerifierTraits);
    163 };
    164 
    165 typedef GenericScopedHandle<HandleTraits, VerifierTraits> ScopedHandle;
    166 
    167 // This function may be called by the embedder to disable the use of
    168 // VerifierTraits at runtime. It has no effect if DummyVerifierTraits is used
    169 // for ScopedHandle.
    170 void BASE_EXPORT DisableHandleVerifier();
    171 
    172 // This should be called whenever the OS is closing a handle, if extended
    173 // verification of improper handle closing is desired. If |handle| is being
    174 // tracked by the handle verifier and ScopedHandle is not the one closing it,
    175 // a CHECK is generated.
    176 void BASE_EXPORT OnHandleBeingClosed(HANDLE handle);
    177 
    178 }  // namespace win
    179 }  // namespace base
    180 
    181 #endif  // BASE_SCOPED_HANDLE_WIN_H_
    182