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 GenericScopedHandle()40 GenericScopedHandle() : handle_(Traits::NullHandle()) {} 41 GenericScopedHandle(Handle handle)42 explicit GenericScopedHandle(Handle handle) : handle_(Traits::NullHandle()) { 43 Set(handle); 44 } 45 46 // Move constructor for C++03 move emulation of this type. GenericScopedHandle(RValue other)47 GenericScopedHandle(RValue other) : handle_(Traits::NullHandle()) { 48 Set(other.object->Take()); 49 } 50 ~GenericScopedHandle()51 ~GenericScopedHandle() { 52 Close(); 53 } 54 IsValid()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 Set(Handle handle)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 Get()79 Handle Get() const { 80 return handle_; 81 } 82 Handle()83 operator Handle() const { 84 return handle_; 85 } 86 87 // Transfers ownership away from this object. Take()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. Close()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. IsHandleValid(HANDLE handle)124 static bool IsHandleValid(HANDLE handle) { 125 return handle != NULL && handle != INVALID_HANDLE_VALUE; 126 } 127 128 // Returns NULL handle value. NullHandle()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 StartTracking(HANDLE handle,const void * owner,const void * pc1,const void * pc2)142 static void StartTracking(HANDLE handle, const void* owner, 143 const void* pc1, const void* pc2) {} StopTracking(HANDLE handle,const void * owner,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