// 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 { // Closes the provided handle if it is not NULL. void CheckAndCloseHandle(HANDLE handle) { if (!handle) return; if (::CloseHandle(handle)) return; CHECK(false); } // 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, HANDLE* target) { if (!source) return true; HANDLE temp = NULL; if (!::DuplicateHandle(::GetCurrentProcess(), source, ::GetCurrentProcess(), &temp, 0, FALSE, DUPLICATE_SAME_ACCESS)) { DPLOG(ERROR) << "Failed to duplicate a handle."; return false; } *target = temp; return true; } } // namespace ScopedProcessInformation::ScopedProcessInformation() : process_information_() { } ScopedProcessInformation::~ScopedProcessInformation() { Close(); } PROCESS_INFORMATION* ScopedProcessInformation::Receive() { DCHECK(!IsValid()) << "process_information_ must be NULL"; return &process_information_; } bool ScopedProcessInformation::IsValid() const { return process_information_.hThread || process_information_.hProcess || process_information_.dwProcessId || process_information_.dwThreadId; } void ScopedProcessInformation::Close() { CheckAndCloseHandle(process_information_.hThread); CheckAndCloseHandle(process_information_.hProcess); Reset(); } void ScopedProcessInformation::Swap(ScopedProcessInformation* other) { DCHECK(other); PROCESS_INFORMATION temp = other->process_information_; other->process_information_ = process_information_; process_information_ = temp; } bool ScopedProcessInformation::DuplicateFrom( const ScopedProcessInformation& other) { DCHECK(!IsValid()) << "target ScopedProcessInformation must be NULL"; DCHECK(other.IsValid()) << "source ScopedProcessInformation must be valid"; ScopedHandle duplicate_process; ScopedHandle duplicate_thread; if (CheckAndDuplicateHandle(other.process_handle(), duplicate_process.Receive()) && CheckAndDuplicateHandle(other.thread_handle(), duplicate_thread.Receive())) { process_information_.dwProcessId = other.process_id(); process_information_.dwThreadId = other.thread_id(); process_information_.hProcess = duplicate_process.Take(); process_information_.hThread = duplicate_thread.Take(); return true; } return false; } PROCESS_INFORMATION ScopedProcessInformation::Take() { PROCESS_INFORMATION process_information = process_information_; Reset(); return process_information; } HANDLE ScopedProcessInformation::TakeProcessHandle() { HANDLE process = process_information_.hProcess; process_information_.hProcess = NULL; process_information_.dwProcessId = 0; return process; } HANDLE ScopedProcessInformation::TakeThreadHandle() { HANDLE thread = process_information_.hThread; process_information_.hThread = NULL; process_information_.dwThreadId = 0; return thread; } void ScopedProcessInformation::Reset() { process_information_.hThread = NULL; process_information_.hProcess = NULL; process_information_.dwProcessId = 0; process_information_.dwThreadId = 0; } } // namespace win } // namespace base