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