15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef BASE_WIN_SCOPED_HANDLE_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_WIN_SCOPED_HANDLE_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_export.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/move.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(rvargas): remove this with the rest of the verifier. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(COMPILER_MSVC) 184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <intrin.h> 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_WIN_GET_CALLER _ReturnAddress() 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(COMPILER_GCC) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_WIN_GET_CALLER __builtin_extract_return_addr(\\ 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __builtin_return_address(0)) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace base { 264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace win { 274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Generic wrapper for raw handles that takes care of closing handles 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// automatically. The class interface follows the style of 30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// the ScopedFILE class with one addition: 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - IsValid() method can tolerate multiple invalid handle values such as NULL 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and INVALID_HANDLE_VALUE (-1) for Win32 handles. 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class Traits, class Verifier> 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GenericScopedHandle { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MOVE_ONLY_TYPE_FOR_CPP_03(GenericScopedHandle, RValue) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef typename Traits::Handle Handle; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GenericScopedHandle() : handle_(Traits::NullHandle()) {} 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit GenericScopedHandle(Handle handle) : handle_(Traits::NullHandle()) { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Set(handle); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Move constructor for C++03 move emulation of this type. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GenericScopedHandle(RValue other) : handle_(Traits::NullHandle()) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Set(other.object->Take()); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~GenericScopedHandle() { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Close(); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool IsValid() const { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Traits::IsHandleValid(handle_); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Move operator= for C++03 move emulation of this type. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GenericScopedHandle& operator=(RValue other) { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this != other.object) { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Set(other.object->Take()); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *this; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Set(Handle handle) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (handle_ != handle) { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Close(); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (Traits::IsHandleValid(handle)) { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handle_ = handle; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Verifier::StartTracking(handle, this, BASE_WIN_GET_CALLER, 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracked_objects::GetProgramCounter()); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Handle Get() const { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return handle_; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) operator Handle() const { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return handle_; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Transfers ownership away from this object. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Handle Take() { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Handle temp = handle_; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handle_ = Traits::NullHandle(); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (Traits::IsHandleValid(temp)) { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Verifier::StopTracking(temp, this, BASE_WIN_GET_CALLER, 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracked_objects::GetProgramCounter()); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return temp; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Explicitly closes the owned handle. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Close() { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (Traits::IsHandleValid(handle_)) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Verifier::StopTracking(handle_, this, BASE_WIN_GET_CALLER, 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracked_objects::GetProgramCounter()); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Traits::CloseHandle(handle_); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handle_ = Traits::NullHandle(); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Handle handle_; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef BASE_WIN_GET_CALLER 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The traits class for Win32 handles that can be closed via CloseHandle() API. 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class HandleTraits { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef HANDLE Handle; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Closes the handle. 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static bool BASE_EXPORT CloseHandle(HANDLE handle); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true if the handle value is valid. 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool IsHandleValid(HANDLE handle) { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return handle != NULL && handle != INVALID_HANDLE_VALUE; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns NULL handle value. 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static HANDLE NullHandle() { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_IMPLICIT_CONSTRUCTORS(HandleTraits); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Do-nothing verifier. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DummyVerifierTraits { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef HANDLE Handle; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void StartTracking(HANDLE handle, const void* owner, 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* pc1, const void* pc2) {} 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void StopTracking(HANDLE handle, const void* owner, 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* pc1, const void* pc2) {} 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_IMPLICIT_CONSTRUCTORS(DummyVerifierTraits); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Performs actual run-time tracking. 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BASE_EXPORT VerifierTraits { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef HANDLE Handle; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void StartTracking(HANDLE handle, const void* owner, 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* pc1, const void* pc2); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void StopTracking(HANDLE handle, const void* owner, 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* pc1, const void* pc2); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_IMPLICIT_CONSTRUCTORS(VerifierTraits); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef GenericScopedHandle<HandleTraits, VerifierTraits> ScopedHandle; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// This function may be called by the embedder to disable the use of 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// VerifierTraits at runtime. It has no effect if DummyVerifierTraits is used 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// for ScopedHandle. 1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BASE_EXPORT DisableHandleVerifier(); 1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// This should be called whenever the OS is closing a handle, if extended 1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// verification of improper handle closing is desired. If |handle| is being 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// tracked by the handle verifier and ScopedHandle is not the one closing it, 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// a CHECK is generated. 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BASE_EXPORT OnHandleBeingClosed(HANDLE handle); 1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace win 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // BASE_SCOPED_HANDLE_WIN_H_ 182