scoped_process_information.cc (2953B)
1 // Copyright 2012 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/win/scoped_process_information.h" 6 7 #include "base/logging.h" 8 #include "base/win/scoped_handle.h" 9 10 namespace base { 11 namespace win { 12 13 namespace { 14 15 // Duplicates source into target, returning true upon success. |target| is 16 // guaranteed to be untouched in case of failure. Succeeds with no side-effects 17 // if source is NULL. 18 bool CheckAndDuplicateHandle(HANDLE source, ScopedHandle* target) { 19 if (!source) 20 return true; 21 22 HANDLE temp = nullptr; 23 if (!::DuplicateHandle(::GetCurrentProcess(), source, ::GetCurrentProcess(), 24 &temp, 0, FALSE, DUPLICATE_SAME_ACCESS)) { 25 DWORD last_error = ::GetLastError(); 26 DPLOG(ERROR) << "Failed to duplicate a handle " << last_error; 27 ::SetLastError(last_error); 28 return false; 29 } 30 target->Set(temp); 31 return true; 32 } 33 34 } // namespace 35 36 ScopedProcessInformation::ScopedProcessInformation() = default; 37 38 ScopedProcessInformation::ScopedProcessInformation( 39 const PROCESS_INFORMATION& process_info) { 40 Set(process_info); 41 } 42 43 ScopedProcessInformation::~ScopedProcessInformation() { 44 Close(); 45 } 46 47 bool ScopedProcessInformation::IsValid() const { 48 return process_id_ || process_handle_.get() || thread_id_ || 49 thread_handle_.get(); 50 } 51 52 void ScopedProcessInformation::Close() { 53 process_handle_.Close(); 54 thread_handle_.Close(); 55 process_id_ = 0; 56 thread_id_ = 0; 57 } 58 59 void ScopedProcessInformation::Set(const PROCESS_INFORMATION& process_info) { 60 if (IsValid()) 61 Close(); 62 63 process_handle_.Set(process_info.hProcess); 64 thread_handle_.Set(process_info.hThread); 65 process_id_ = process_info.dwProcessId; 66 thread_id_ = process_info.dwThreadId; 67 } 68 69 bool ScopedProcessInformation::DuplicateFrom( 70 const ScopedProcessInformation& other) { 71 DCHECK(!IsValid()) << "target ScopedProcessInformation must be NULL"; 72 DCHECK(other.IsValid()) << "source ScopedProcessInformation must be valid"; 73 74 if (CheckAndDuplicateHandle(other.process_handle(), &process_handle_) && 75 CheckAndDuplicateHandle(other.thread_handle(), &thread_handle_)) { 76 process_id_ = other.process_id(); 77 thread_id_ = other.thread_id(); 78 return true; 79 } 80 81 return false; 82 } 83 84 PROCESS_INFORMATION ScopedProcessInformation::Take() { 85 PROCESS_INFORMATION process_information = {}; 86 process_information.hProcess = process_handle_.release(); 87 process_information.hThread = thread_handle_.release(); 88 process_information.dwProcessId = process_id(); 89 process_information.dwThreadId = thread_id(); 90 process_id_ = 0; 91 thread_id_ = 0; 92 93 return process_information; 94 } 95 96 HANDLE ScopedProcessInformation::TakeProcessHandle() { 97 process_id_ = 0; 98 return process_handle_.release(); 99 } 100 101 HANDLE ScopedProcessInformation::TakeThreadHandle() { 102 thread_id_ = 0; 103 return thread_handle_.release(); 104 } 105 106 } // namespace win 107 } // namespace base