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 #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, HANDLE* target) { 19 if (!source) 20 return true; 21 22 HANDLE temp = NULL; 23 if (!::DuplicateHandle(::GetCurrentProcess(), source, 24 ::GetCurrentProcess(), &temp, 0, FALSE, 25 DUPLICATE_SAME_ACCESS)) { 26 DPLOG(ERROR) << "Failed to duplicate a handle."; 27 return false; 28 } 29 *target = temp; 30 return true; 31 } 32 33 } // namespace 34 35 ScopedProcessInformation::ScopedProcessInformation() 36 : process_id_(0), thread_id_(0) { 37 } 38 39 ScopedProcessInformation::~ScopedProcessInformation() { 40 Close(); 41 } 42 43 ScopedProcessInformation::Receiver ScopedProcessInformation::Receive() { 44 DCHECK(!IsValid()) << "process_information_ must be NULL"; 45 return Receiver(this); 46 } 47 48 bool ScopedProcessInformation::IsValid() const { 49 return process_id_ || process_handle_.Get() || 50 thread_id_ || thread_handle_.Get(); 51 } 52 53 void ScopedProcessInformation::Close() { 54 process_handle_.Close(); 55 thread_handle_.Close(); 56 process_id_ = 0; 57 thread_id_ = 0; 58 } 59 60 void ScopedProcessInformation::Set(const PROCESS_INFORMATION& process_info) { 61 if (IsValid()) 62 Close(); 63 64 process_handle_.Set(process_info.hProcess); 65 thread_handle_.Set(process_info.hThread); 66 process_id_ = process_info.dwProcessId; 67 thread_id_ = process_info.dwThreadId; 68 } 69 70 bool ScopedProcessInformation::DuplicateFrom( 71 const ScopedProcessInformation& other) { 72 DCHECK(!IsValid()) << "target ScopedProcessInformation must be NULL"; 73 DCHECK(other.IsValid()) << "source ScopedProcessInformation must be valid"; 74 75 if (CheckAndDuplicateHandle(other.process_handle(), 76 process_handle_.Receive()) && 77 CheckAndDuplicateHandle(other.thread_handle(), 78 thread_handle_.Receive())) { 79 process_id_ = other.process_id(); 80 thread_id_ = other.thread_id(); 81 return true; 82 } 83 84 return false; 85 } 86 87 PROCESS_INFORMATION ScopedProcessInformation::Take() { 88 PROCESS_INFORMATION process_information = {}; 89 process_information.hProcess = process_handle_.Take(); 90 process_information.hThread = thread_handle_.Take(); 91 process_information.dwProcessId = process_id(); 92 process_information.dwThreadId = thread_id(); 93 process_id_ = 0; 94 thread_id_ = 0; 95 96 return process_information; 97 } 98 99 HANDLE ScopedProcessInformation::TakeProcessHandle() { 100 process_id_ = 0; 101 return process_handle_.Take(); 102 } 103 104 HANDLE ScopedProcessInformation::TakeThreadHandle() { 105 thread_id_ = 0; 106 return thread_handle_.Take(); 107 } 108 109 } // namespace win 110 } // namespace base 111