// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/win/scoped_process_information.h" #include "base/logging.h" #include "base/win/scoped_handle.h" namespace base { namespace win { namespace { // Duplicates source into target, returning true upon success. |target| is // guaranteed to be untouched in case of failure. Succeeds with no side-effects // if source is NULL. bool CheckAndDuplicateHandle(HANDLE source, ScopedHandle* target) { if (!source) return true; HANDLE temp = NULL; if (!::DuplicateHandle(::GetCurrentProcess(), source, ::GetCurrentProcess(), &temp, 0, FALSE, DUPLICATE_SAME_ACCESS)) { DWORD last_error = ::GetLastError(); DPLOG(ERROR) << "Failed to duplicate a handle " << last_error; ::SetLastError(last_error); return false; } target->Set(temp); return true; } } // namespace ScopedProcessInformation::ScopedProcessInformation() : process_id_(0), thread_id_(0) {} ScopedProcessInformation::ScopedProcessInformation( const PROCESS_INFORMATION& process_info) : process_id_(0), thread_id_(0) { Set(process_info); } ScopedProcessInformation::~ScopedProcessInformation() { Close(); } bool ScopedProcessInformation::IsValid() const { return process_id_ || process_handle_.Get() || thread_id_ || thread_handle_.Get(); } void ScopedProcessInformation::Close() { process_handle_.Close(); thread_handle_.Close(); process_id_ = 0; thread_id_ = 0; } void ScopedProcessInformation::Set(const PROCESS_INFORMATION& process_info) { if (IsValid()) Close(); process_handle_.Set(process_info.hProcess); thread_handle_.Set(process_info.hThread); process_id_ = process_info.dwProcessId; thread_id_ = process_info.dwThreadId; } bool ScopedProcessInformation::DuplicateFrom( const ScopedProcessInformation& other) { DCHECK(!IsValid()) << "target ScopedProcessInformation must be NULL"; DCHECK(other.IsValid()) << "source ScopedProcessInformation must be valid"; if (CheckAndDuplicateHandle(other.process_handle(), &process_handle_) && CheckAndDuplicateHandle(other.thread_handle(), &thread_handle_)) { process_id_ = other.process_id(); thread_id_ = other.thread_id(); return true; } return false; } PROCESS_INFORMATION ScopedProcessInformation::Take() { PROCESS_INFORMATION process_information = {}; process_information.hProcess = process_handle_.Take(); process_information.hThread = thread_handle_.Take(); process_information.dwProcessId = process_id(); process_information.dwThreadId = thread_id(); process_id_ = 0; thread_id_ = 0; return process_information; } HANDLE ScopedProcessInformation::TakeProcessHandle() { process_id_ = 0; return process_handle_.Take(); } HANDLE ScopedProcessInformation::TakeThreadHandle() { thread_id_ = 0; return thread_handle_.Take(); } } // namespace win } // namespace base