1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
|
// Copyright 2012 The Chromium Authors
// 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 = nullptr;
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() = default;
ScopedProcessInformation::ScopedProcessInformation(
const PROCESS_INFORMATION& process_info) {
Set(process_info);
}
ScopedProcessInformation::ScopedProcessInformation(ScopedProcessInformation&&) =
default;
ScopedProcessInformation& ScopedProcessInformation::operator=(
ScopedProcessInformation&&) = default;
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_.release();
process_information.hThread = thread_handle_.release();
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_.release();
}
HANDLE ScopedProcessInformation::TakeThreadHandle() {
thread_id_ = 0;
return thread_handle_.release();
}
} // namespace win
} // namespace base
|