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 ScopedStdioHandle class with a few additions: 31 // - IsValid() method can tolerate multiple invalid handle values such as NULL 32 // and INVALID_HANDLE_VALUE (-1) for Win32 handles. 33 // - Receive() method allows to receive a handle value from a function that 34 // takes a raw handle pointer only. 35 template <class Traits, class Verifier> 36 class GenericScopedHandle { 37 MOVE_ONLY_TYPE_FOR_CPP_03(GenericScopedHandle, RValue) 38 39 public: 40 typedef typename Traits::Handle Handle; 41 42 GenericScopedHandle() : handle_(Traits::NullHandle()) {} 43 44 explicit GenericScopedHandle(Handle handle) : handle_(Traits::NullHandle()) { 45 Set(handle); 46 } 47 48 // Move constructor for C++03 move emulation of this type. 49 GenericScopedHandle(RValue other) : handle_(Traits::NullHandle()) { 50 Set(other.object->Take()); 51 } 52 53 ~GenericScopedHandle() { 54 Close(); 55 } 56 57 bool IsValid() const { 58 return Traits::IsHandleValid(handle_); 59 } 60 61 // Move operator= for C++03 move emulation of this type. 62 GenericScopedHandle& operator=(RValue other) { 63 if (this != other.object) { 64 Set(other.object->Take()); 65 } 66 return *this; 67 } 68 69 void Set(Handle handle) { 70 if (handle_ != handle) { 71 Close(); 72 73 if (Traits::IsHandleValid(handle)) { 74 handle_ = handle; 75 Verifier::StartTracking(handle, this, BASE_WIN_GET_CALLER, 76 tracked_objects::GetProgramCounter()); 77 } 78 } 79 } 80 81 Handle Get() const { 82 return handle_; 83 } 84 85 operator Handle() const { 86 return handle_; 87 } 88 89 // Transfers ownership away from this object. 90 Handle Take() { 91 Handle temp = handle_; 92 handle_ = Traits::NullHandle(); 93 if (Traits::IsHandleValid(temp)) { 94 Verifier::StopTracking(temp, this, BASE_WIN_GET_CALLER, 95 tracked_objects::GetProgramCounter()); 96 } 97 return temp; 98 } 99 100 // Explicitly closes the owned handle. 101 void Close() { 102 if (Traits::IsHandleValid(handle_)) { 103 Verifier::StopTracking(handle_, this, BASE_WIN_GET_CALLER, 104 tracked_objects::GetProgramCounter()); 105 106 if (!Traits::CloseHandle(handle_)) 107 CHECK(false); 108 109 handle_ = Traits::NullHandle(); 110 } 111 } 112 113 private: 114 Handle handle_; 115 }; 116 117 #undef BASE_WIN_GET_CALLER 118 119 // The traits class for Win32 handles that can be closed via CloseHandle() API. 120 class HandleTraits { 121 public: 122 typedef HANDLE Handle; 123 124 // Closes the handle. 125 static bool CloseHandle(HANDLE handle) { 126 return ::CloseHandle(handle) != FALSE; 127 } 128 129 // Returns true if the handle value is valid. 130 static bool IsHandleValid(HANDLE handle) { 131 return handle != NULL && handle != INVALID_HANDLE_VALUE; 132 } 133 134 // Returns NULL handle value. 135 static HANDLE NullHandle() { 136 return NULL; 137 } 138 139 private: 140 DISALLOW_IMPLICIT_CONSTRUCTORS(HandleTraits); 141 }; 142 143 // Do-nothing verifier. 144 class DummyVerifierTraits { 145 public: 146 typedef HANDLE Handle; 147 148 static void StartTracking(HANDLE handle, const void* owner, 149 const void* pc1, const void* pc2) {} 150 static void StopTracking(HANDLE handle, const void* owner, 151 const void* pc1, const void* pc2) {} 152 153 private: 154 DISALLOW_IMPLICIT_CONSTRUCTORS(DummyVerifierTraits); 155 }; 156 157 // Performs actual run-time tracking. 158 class BASE_EXPORT VerifierTraits { 159 public: 160 typedef HANDLE Handle; 161 162 static void StartTracking(HANDLE handle, const void* owner, 163 const void* pc1, const void* pc2); 164 static void StopTracking(HANDLE handle, const void* owner, 165 const void* pc1, const void* pc2); 166 167 private: 168 DISALLOW_IMPLICIT_CONSTRUCTORS(VerifierTraits); 169 }; 170 171 typedef GenericScopedHandle<HandleTraits, VerifierTraits> ScopedHandle; 172 173 } // namespace win 174 } // namespace base 175 176 #endif // BASE_SCOPED_HANDLE_WIN_H_ 177