• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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