• 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 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 
GenericScopedHandle()42   GenericScopedHandle() : handle_(Traits::NullHandle()) {}
43 
GenericScopedHandle(Handle handle)44   explicit GenericScopedHandle(Handle handle) : handle_(Traits::NullHandle()) {
45     Set(handle);
46   }
47 
48   // Move constructor for C++03 move emulation of this type.
GenericScopedHandle(RValue other)49   GenericScopedHandle(RValue other) : handle_(Traits::NullHandle()) {
50     Set(other.object->Take());
51   }
52 
~GenericScopedHandle()53   ~GenericScopedHandle() {
54     Close();
55   }
56 
IsValid()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 
Set(Handle handle)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 
Get()81   Handle Get() const {
82     return handle_;
83   }
84 
Handle()85   operator Handle() const {
86     return handle_;
87   }
88 
89   // Transfers ownership away from this object.
Take()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.
Close()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.
CloseHandle(HANDLE handle)125   static bool CloseHandle(HANDLE handle) {
126     return ::CloseHandle(handle) != FALSE;
127   }
128 
129   // Returns true if the handle value is valid.
IsHandleValid(HANDLE handle)130   static bool IsHandleValid(HANDLE handle) {
131     return handle != NULL && handle != INVALID_HANDLE_VALUE;
132   }
133 
134   // Returns NULL handle value.
NullHandle()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 
StartTracking(HANDLE handle,const void * owner,const void * pc1,const void * pc2)148   static void StartTracking(HANDLE handle, const void* owner,
149                             const void* pc1, const void* pc2) {}
StopTracking(HANDLE handle,const void * owner,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