Use UintToString() for unsigned values.
[chromium-blink-merge.git] / base / win / scoped_process_information.cc
blob634a538eece513e8218a47a9ae72fb36bb54b005
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.
5 #include "base/win/scoped_process_information.h"
7 #include "base/logging.h"
8 #include "base/win/scoped_handle.h"
9 #include "base/win/windows_version.h"
11 namespace base {
12 namespace win {
14 namespace {
16 // Duplicates source into target, returning true upon success. |target| is
17 // guaranteed to be untouched in case of failure. Succeeds with no side-effects
18 // if source is NULL.
19 bool CheckAndDuplicateHandle(HANDLE source, ScopedHandle* target) {
20 if (!source)
21 return true;
23 HANDLE temp = NULL;
25 // TODO(shrikant): Remove following code as soon as we gather some
26 // information regarding AppContainer related DuplicateHandle failures that
27 // only seem to happen on certain machine and only random launches (normally
28 // renderer launches seem to succeed even on those machines.)
29 if (base::win::GetVersion() == base::win::VERSION_WIN8 ||
30 base::win::GetVersion() == base::win::VERSION_WIN8_1) {
31 typedef LONG (WINAPI *NtDuplicateObject)(
32 IN HANDLE SourceProcess,
33 IN HANDLE SourceHandle,
34 IN HANDLE TargetProcess,
35 OUT PHANDLE TargetHandle,
36 IN ACCESS_MASK DesiredAccess,
37 IN ULONG Attributes,
38 IN ULONG Options);
40 typedef ULONG (WINAPI *RtlNtStatusToDosError)(IN LONG Status);
42 NtDuplicateObject nt_duplicate_object =
43 reinterpret_cast<NtDuplicateObject>(::GetProcAddress(
44 GetModuleHandle(L"ntdll.dll"), "NtDuplicateObject"));
45 if (nt_duplicate_object != NULL) {
46 LONG status = nt_duplicate_object(::GetCurrentProcess(), source,
47 ::GetCurrentProcess(), &temp,
48 0, FALSE, DUPLICATE_SAME_ACCESS);
49 if (status < 0) {
50 DPLOG(ERROR) << "Failed to duplicate a handle.";
51 RtlNtStatusToDosError ntstatus_to_doserror =
52 reinterpret_cast<RtlNtStatusToDosError>(::GetProcAddress(
53 GetModuleHandle(L"ntdll.dll"), "RtlNtStatusToDosError"));
54 if (ntstatus_to_doserror != NULL) {
55 ::SetLastError(ntstatus_to_doserror(status));
57 return false;
60 } else {
61 if (!::DuplicateHandle(::GetCurrentProcess(), source,
62 ::GetCurrentProcess(), &temp, 0, FALSE,
63 DUPLICATE_SAME_ACCESS)) {
64 DPLOG(ERROR) << "Failed to duplicate a handle.";
65 return false;
68 target->Set(temp);
69 return true;
72 } // namespace
74 ScopedProcessInformation::ScopedProcessInformation()
75 : process_id_(0), thread_id_(0) {
78 ScopedProcessInformation::ScopedProcessInformation(
79 const PROCESS_INFORMATION& process_info) : process_id_(0), thread_id_(0) {
80 Set(process_info);
83 ScopedProcessInformation::~ScopedProcessInformation() {
84 Close();
87 bool ScopedProcessInformation::IsValid() const {
88 return process_id_ || process_handle_.Get() ||
89 thread_id_ || thread_handle_.Get();
92 void ScopedProcessInformation::Close() {
93 process_handle_.Close();
94 thread_handle_.Close();
95 process_id_ = 0;
96 thread_id_ = 0;
99 void ScopedProcessInformation::Set(const PROCESS_INFORMATION& process_info) {
100 if (IsValid())
101 Close();
103 process_handle_.Set(process_info.hProcess);
104 thread_handle_.Set(process_info.hThread);
105 process_id_ = process_info.dwProcessId;
106 thread_id_ = process_info.dwThreadId;
109 bool ScopedProcessInformation::DuplicateFrom(
110 const ScopedProcessInformation& other) {
111 DCHECK(!IsValid()) << "target ScopedProcessInformation must be NULL";
112 DCHECK(other.IsValid()) << "source ScopedProcessInformation must be valid";
114 if (CheckAndDuplicateHandle(other.process_handle(), &process_handle_) &&
115 CheckAndDuplicateHandle(other.thread_handle(), &thread_handle_)) {
116 process_id_ = other.process_id();
117 thread_id_ = other.thread_id();
118 return true;
121 return false;
124 PROCESS_INFORMATION ScopedProcessInformation::Take() {
125 PROCESS_INFORMATION process_information = {};
126 process_information.hProcess = process_handle_.Take();
127 process_information.hThread = thread_handle_.Take();
128 process_information.dwProcessId = process_id();
129 process_information.dwThreadId = thread_id();
130 process_id_ = 0;
131 thread_id_ = 0;
133 return process_information;
136 HANDLE ScopedProcessInformation::TakeProcessHandle() {
137 process_id_ = 0;
138 return process_handle_.Take();
141 HANDLE ScopedProcessInformation::TakeThreadHandle() {
142 thread_id_ = 0;
143 return thread_handle_.Take();
146 } // namespace win
147 } // namespace base