16d528ed9Sopenharmony_ci// Copyright (c) 2012 The Chromium Authors. All rights reserved. 26d528ed9Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 36d528ed9Sopenharmony_ci// found in the LICENSE file. 46d528ed9Sopenharmony_ci 56d528ed9Sopenharmony_ci#ifndef BASE_WIN_SCOPED_HANDLE_H_ 66d528ed9Sopenharmony_ci#define BASE_WIN_SCOPED_HANDLE_H_ 76d528ed9Sopenharmony_ci 86d528ed9Sopenharmony_ci#include <windows.h> 96d528ed9Sopenharmony_ci 106d528ed9Sopenharmony_ci#include "base/gtest_prod_util.h" 116d528ed9Sopenharmony_ci#include "base/logging.h" 126d528ed9Sopenharmony_ci 136d528ed9Sopenharmony_ci// TODO(rvargas): remove this with the rest of the verifier. 146d528ed9Sopenharmony_ci#if defined(COMPILER_MSVC) 156d528ed9Sopenharmony_ci#include <intrin.h> 166d528ed9Sopenharmony_ci#define BASE_WIN_GET_CALLER _ReturnAddress() 176d528ed9Sopenharmony_ci#elif defined(COMPILER_GCC) 186d528ed9Sopenharmony_ci#define BASE_WIN_GET_CALLER \ 196d528ed9Sopenharmony_ci __builtin_extract_return_addr(\ __builtin_return_address(0)) 206d528ed9Sopenharmony_ci#endif 216d528ed9Sopenharmony_ci 226d528ed9Sopenharmony_cinamespace base { 236d528ed9Sopenharmony_cinamespace win { 246d528ed9Sopenharmony_ci 256d528ed9Sopenharmony_ci// Generic wrapper for raw handles that takes care of closing handles 266d528ed9Sopenharmony_ci// automatically. The class interface follows the style of 276d528ed9Sopenharmony_ci// the ScopedFILE class with two additions: 286d528ed9Sopenharmony_ci// - IsValid() method can tolerate multiple invalid handle values such as NULL 296d528ed9Sopenharmony_ci// and INVALID_HANDLE_VALUE (-1) for Win32 handles. 306d528ed9Sopenharmony_ci// - Set() (and the constructors and assignment operators that call it) 316d528ed9Sopenharmony_ci// preserve the Windows LastError code. This ensures that GetLastError() can 326d528ed9Sopenharmony_ci// be called after stashing a handle in a GenericScopedHandle object. Doing 336d528ed9Sopenharmony_ci// this explicitly is necessary because of bug 528394 and VC++ 2015. 346d528ed9Sopenharmony_citemplate <class Traits, class Verifier> 356d528ed9Sopenharmony_ciclass GenericScopedHandle { 366d528ed9Sopenharmony_ci public: 376d528ed9Sopenharmony_ci typedef typename Traits::Handle Handle; 386d528ed9Sopenharmony_ci 396d528ed9Sopenharmony_ci GenericScopedHandle() : handle_(Traits::NullHandle()) {} 406d528ed9Sopenharmony_ci 416d528ed9Sopenharmony_ci explicit GenericScopedHandle(Handle handle) : handle_(Traits::NullHandle()) { 426d528ed9Sopenharmony_ci Set(handle); 436d528ed9Sopenharmony_ci } 446d528ed9Sopenharmony_ci 456d528ed9Sopenharmony_ci GenericScopedHandle(GenericScopedHandle&& other) 466d528ed9Sopenharmony_ci : handle_(Traits::NullHandle()) { 476d528ed9Sopenharmony_ci Set(other.Take()); 486d528ed9Sopenharmony_ci } 496d528ed9Sopenharmony_ci 506d528ed9Sopenharmony_ci ~GenericScopedHandle() { Close(); } 516d528ed9Sopenharmony_ci 526d528ed9Sopenharmony_ci bool IsValid() const { return Traits::IsHandleValid(handle_); } 536d528ed9Sopenharmony_ci 546d528ed9Sopenharmony_ci GenericScopedHandle& operator=(GenericScopedHandle&& other) { 556d528ed9Sopenharmony_ci DCHECK_NE(this, &other); 566d528ed9Sopenharmony_ci Set(other.Take()); 576d528ed9Sopenharmony_ci return *this; 586d528ed9Sopenharmony_ci } 596d528ed9Sopenharmony_ci 606d528ed9Sopenharmony_ci void Set(Handle handle) { 616d528ed9Sopenharmony_ci if (handle_ != handle) { 626d528ed9Sopenharmony_ci // Preserve old LastError to avoid bug 528394. 636d528ed9Sopenharmony_ci auto last_error = ::GetLastError(); 646d528ed9Sopenharmony_ci Close(); 656d528ed9Sopenharmony_ci 666d528ed9Sopenharmony_ci if (Traits::IsHandleValid(handle)) { 676d528ed9Sopenharmony_ci handle_ = handle; 686d528ed9Sopenharmony_ci } 696d528ed9Sopenharmony_ci ::SetLastError(last_error); 706d528ed9Sopenharmony_ci } 716d528ed9Sopenharmony_ci } 726d528ed9Sopenharmony_ci 736d528ed9Sopenharmony_ci Handle Get() const { return handle_; } 746d528ed9Sopenharmony_ci 756d528ed9Sopenharmony_ci // Transfers ownership away from this object. 766d528ed9Sopenharmony_ci Handle Take() { 776d528ed9Sopenharmony_ci Handle temp = handle_; 786d528ed9Sopenharmony_ci handle_ = Traits::NullHandle(); 796d528ed9Sopenharmony_ci return temp; 806d528ed9Sopenharmony_ci } 816d528ed9Sopenharmony_ci 826d528ed9Sopenharmony_ci // Explicitly closes the owned handle. 836d528ed9Sopenharmony_ci void Close() { 846d528ed9Sopenharmony_ci if (Traits::IsHandleValid(handle_)) { 856d528ed9Sopenharmony_ci Traits::CloseHandle(handle_); 866d528ed9Sopenharmony_ci handle_ = Traits::NullHandle(); 876d528ed9Sopenharmony_ci } 886d528ed9Sopenharmony_ci } 896d528ed9Sopenharmony_ci 906d528ed9Sopenharmony_ci private: 916d528ed9Sopenharmony_ci FRIEND_TEST_ALL_PREFIXES(ScopedHandleTest, ActiveVerifierWrongOwner); 926d528ed9Sopenharmony_ci FRIEND_TEST_ALL_PREFIXES(ScopedHandleTest, ActiveVerifierUntrackedHandle); 936d528ed9Sopenharmony_ci Handle handle_; 946d528ed9Sopenharmony_ci 956d528ed9Sopenharmony_ci GenericScopedHandle(const GenericScopedHandle&) = delete; 966d528ed9Sopenharmony_ci GenericScopedHandle& operator=(const GenericScopedHandle&) = delete; 976d528ed9Sopenharmony_ci}; 986d528ed9Sopenharmony_ci 996d528ed9Sopenharmony_ci#undef BASE_WIN_GET_CALLER 1006d528ed9Sopenharmony_ci 1016d528ed9Sopenharmony_ci// The traits class for Win32 handles that can be closed via CloseHandle() API. 1026d528ed9Sopenharmony_ciclass HandleTraits { 1036d528ed9Sopenharmony_ci public: 1046d528ed9Sopenharmony_ci typedef HANDLE Handle; 1056d528ed9Sopenharmony_ci 1066d528ed9Sopenharmony_ci // Closes the handle. 1076d528ed9Sopenharmony_ci static bool CloseHandle(HANDLE handle); 1086d528ed9Sopenharmony_ci 1096d528ed9Sopenharmony_ci // Returns true if the handle value is valid. 1106d528ed9Sopenharmony_ci static bool IsHandleValid(HANDLE handle) { 1116d528ed9Sopenharmony_ci return handle != NULL && handle != INVALID_HANDLE_VALUE; 1126d528ed9Sopenharmony_ci } 1136d528ed9Sopenharmony_ci 1146d528ed9Sopenharmony_ci // Returns NULL handle value. 1156d528ed9Sopenharmony_ci static HANDLE NullHandle() { return NULL; } 1166d528ed9Sopenharmony_ci 1176d528ed9Sopenharmony_ci private: 1186d528ed9Sopenharmony_ci HandleTraits() = delete; 1196d528ed9Sopenharmony_ci HandleTraits(const HandleTraits&) = delete; 1206d528ed9Sopenharmony_ci HandleTraits& operator=(const HandleTraits&) = delete; 1216d528ed9Sopenharmony_ci}; 1226d528ed9Sopenharmony_ci 1236d528ed9Sopenharmony_ci// Do-nothing verifier. 1246d528ed9Sopenharmony_ciclass DummyVerifierTraits { 1256d528ed9Sopenharmony_ci public: 1266d528ed9Sopenharmony_ci typedef HANDLE Handle; 1276d528ed9Sopenharmony_ci 1286d528ed9Sopenharmony_ci static void StartTracking(HANDLE handle, 1296d528ed9Sopenharmony_ci const void* owner, 1306d528ed9Sopenharmony_ci const void* pc1, 1316d528ed9Sopenharmony_ci const void* pc2) {} 1326d528ed9Sopenharmony_ci static void StopTracking(HANDLE handle, 1336d528ed9Sopenharmony_ci const void* owner, 1346d528ed9Sopenharmony_ci const void* pc1, 1356d528ed9Sopenharmony_ci const void* pc2) {} 1366d528ed9Sopenharmony_ci 1376d528ed9Sopenharmony_ci private: 1386d528ed9Sopenharmony_ci DummyVerifierTraits() = delete; 1396d528ed9Sopenharmony_ci DummyVerifierTraits(const DummyVerifierTraits&) = delete; 1406d528ed9Sopenharmony_ci DummyVerifierTraits& operator=(const DummyVerifierTraits&) = delete; 1416d528ed9Sopenharmony_ci}; 1426d528ed9Sopenharmony_ci 1436d528ed9Sopenharmony_ci// Performs actual run-time tracking. 1446d528ed9Sopenharmony_ciclass VerifierTraits { 1456d528ed9Sopenharmony_ci public: 1466d528ed9Sopenharmony_ci typedef HANDLE Handle; 1476d528ed9Sopenharmony_ci 1486d528ed9Sopenharmony_ci static void StartTracking(HANDLE handle, 1496d528ed9Sopenharmony_ci const void* owner, 1506d528ed9Sopenharmony_ci const void* pc1, 1516d528ed9Sopenharmony_ci const void* pc2); 1526d528ed9Sopenharmony_ci static void StopTracking(HANDLE handle, 1536d528ed9Sopenharmony_ci const void* owner, 1546d528ed9Sopenharmony_ci const void* pc1, 1556d528ed9Sopenharmony_ci const void* pc2); 1566d528ed9Sopenharmony_ci 1576d528ed9Sopenharmony_ci private: 1586d528ed9Sopenharmony_ci VerifierTraits() = delete; 1596d528ed9Sopenharmony_ci VerifierTraits(const VerifierTraits&) = delete; 1606d528ed9Sopenharmony_ci VerifierTraits& operator=(const VerifierTraits&) = delete; 1616d528ed9Sopenharmony_ci}; 1626d528ed9Sopenharmony_ci 1636d528ed9Sopenharmony_citypedef GenericScopedHandle<HandleTraits, VerifierTraits> ScopedHandle; 1646d528ed9Sopenharmony_ci 1656d528ed9Sopenharmony_ci// This function may be called by the embedder to disable the use of 1666d528ed9Sopenharmony_ci// VerifierTraits at runtime. It has no effect if DummyVerifierTraits is used 1676d528ed9Sopenharmony_ci// for ScopedHandle. 1686d528ed9Sopenharmony_civoid DisableHandleVerifier(); 1696d528ed9Sopenharmony_ci 1706d528ed9Sopenharmony_ci// This should be called whenever the OS is closing a handle, if extended 1716d528ed9Sopenharmony_ci// verification of improper handle closing is desired. If |handle| is being 1726d528ed9Sopenharmony_ci// tracked by the handle verifier and ScopedHandle is not the one closing it, 1736d528ed9Sopenharmony_ci// a CHECK is generated. 1746d528ed9Sopenharmony_civoid OnHandleBeingClosed(HANDLE handle); 1756d528ed9Sopenharmony_ci} // namespace win 1766d528ed9Sopenharmony_ci} // namespace base 1776d528ed9Sopenharmony_ci 1786d528ed9Sopenharmony_ci#endif // BASE_WIN_SCOPED_HANDLE_H_ 179