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 namespace base { 17 namespace win { 18 19 // TODO(rvargas): remove this with the rest of the verifier. 20 #if defined(COMPILER_MSVC) 21 // MSDN says to #include <intrin.h>, but that breaks the VS2005 build. 22 extern "C" { 23 void* _ReturnAddress(); 24 } 25 #define BASE_WIN_GET_CALLER _ReturnAddress() 26 #elif defined(COMPILER_GCC) 27 #define BASE_WIN_GET_CALLER __builtin_extract_return_addr(\\ 28 __builtin_return_address(0)) 29 #endif 30 31 // Generic wrapper for raw handles that takes care of closing handles 32 // automatically. The class interface follows the style of 33 // the ScopedStdioHandle class with a few additions: 34 // - IsValid() method can tolerate multiple invalid handle values such as NULL 35 // and INVALID_HANDLE_VALUE (-1) for Win32 handles. 36 // - Receive() method allows to receive a handle value from a function that 37 // takes a raw handle pointer only. 38 template <class Traits, class Verifier> 39 class GenericScopedHandle { 40 MOVE_ONLY_TYPE_FOR_CPP_03(GenericScopedHandle, RValue) 41 42 public: 43 typedef typename Traits::Handle Handle; 44 45 // Helper object to contain the effect of Receive() to the function that needs 46 // a pointer, and allow proper tracking of the handle. 47 class Receiver { 48 public: 49 explicit Receiver(GenericScopedHandle* owner) 50 : handle_(Traits::NullHandle()), 51 owner_(owner) {} 52 ~Receiver() { owner_->Set(handle_); } 53 54 operator Handle*() { return &handle_; } 55 56 private: 57 Handle handle_; 58 GenericScopedHandle* owner_; 59 }; 60 61 GenericScopedHandle() : handle_(Traits::NullHandle()) {} 62 63 explicit GenericScopedHandle(Handle handle) : handle_(Traits::NullHandle()) { 64 Set(handle); 65 } 66 67 // Move constructor for C++03 move emulation of this type. 68 GenericScopedHandle(RValue other) : handle_(Traits::NullHandle()) { 69 Set(other.object->Take()); 70 } 71 72 ~GenericScopedHandle() { 73 Close(); 74 } 75 76 bool IsValid() const { 77 return Traits::IsHandleValid(handle_); 78 } 79 80 // Move operator= for C++03 move emulation of this type. 81 GenericScopedHandle& operator=(RValue other) { 82 if (this != other.object) { 83 Set(other.object->Take()); 84 } 85 return *this; 86 } 87 88 void Set(Handle handle) { 89 if (handle_ != handle) { 90 Close(); 91 92 if (Traits::IsHandleValid(handle)) { 93 handle_ = handle; 94 Verifier::StartTracking(handle, this, BASE_WIN_GET_CALLER, 95 tracked_objects::GetProgramCounter()); 96 } 97 } 98 } 99 100 Handle Get() const { 101 return handle_; 102 } 103 104 operator Handle() const { 105 return handle_; 106 } 107 108 // This method is intended to be used with functions that require a pointer to 109 // a destination handle, like so: 110 // void CreateRequiredHandle(Handle* out_handle); 111 // ScopedHandle a; 112 // CreateRequiredHandle(a.Receive()); 113 Receiver Receive() { 114 DCHECK(!Traits::IsHandleValid(handle_)) << "Handle must be NULL"; 115 return Receiver(this); 116 } 117 118 // Transfers ownership away from this object. 119 Handle Take() { 120 Handle temp = handle_; 121 handle_ = Traits::NullHandle(); 122 if (Traits::IsHandleValid(temp)) { 123 Verifier::StopTracking(temp, this, BASE_WIN_GET_CALLER, 124 tracked_objects::GetProgramCounter()); 125 } 126 return temp; 127 } 128 129 // Explicitly closes the owned handle. 130 void Close() { 131 if (Traits::IsHandleValid(handle_)) { 132 Verifier::StopTracking(handle_, this, BASE_WIN_GET_CALLER, 133 tracked_objects::GetProgramCounter()); 134 135 if (!Traits::CloseHandle(handle_)) 136 CHECK(false); 137 138 handle_ = Traits::NullHandle(); 139 } 140 } 141 142 private: 143 Handle handle_; 144 }; 145 146 #undef BASE_WIN_GET_CALLER 147 148 // The traits class for Win32 handles that can be closed via CloseHandle() API. 149 class HandleTraits { 150 public: 151 typedef HANDLE Handle; 152 153 // Closes the handle. 154 static bool CloseHandle(HANDLE handle) { 155 return ::CloseHandle(handle) != FALSE; 156 } 157 158 // Returns true if the handle value is valid. 159 static bool IsHandleValid(HANDLE handle) { 160 return handle != NULL && handle != INVALID_HANDLE_VALUE; 161 } 162 163 // Returns NULL handle value. 164 static HANDLE NullHandle() { 165 return NULL; 166 } 167 168 private: 169 DISALLOW_IMPLICIT_CONSTRUCTORS(HandleTraits); 170 }; 171 172 // Do-nothing verifier. 173 class DummyVerifierTraits { 174 public: 175 typedef HANDLE Handle; 176 177 static void StartTracking(HANDLE handle, const void* owner, 178 const void* pc1, const void* pc2) {} 179 static void StopTracking(HANDLE handle, const void* owner, 180 const void* pc1, const void* pc2) {} 181 182 private: 183 DISALLOW_IMPLICIT_CONSTRUCTORS(DummyVerifierTraits); 184 }; 185 186 // Performs actual run-time tracking. 187 class BASE_EXPORT VerifierTraits { 188 public: 189 typedef HANDLE Handle; 190 191 static void StartTracking(HANDLE handle, const void* owner, 192 const void* pc1, const void* pc2); 193 static void StopTracking(HANDLE handle, const void* owner, 194 const void* pc1, const void* pc2); 195 196 private: 197 DISALLOW_IMPLICIT_CONSTRUCTORS(VerifierTraits); 198 }; 199 200 typedef GenericScopedHandle<HandleTraits, DummyVerifierTraits> ScopedHandle; 201 202 } // namespace win 203 } // namespace base 204 205 #endif // BASE_SCOPED_HANDLE_WIN_H_ 206