OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/process/process.h" | 5 #include "base/process/process.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
9 #include "base/win/windows_version.h" | 9 #include "base/win/windows_version.h" |
10 | 10 |
11 namespace base { | 11 namespace base { |
12 | 12 |
13 ProcessObject::ProcessObject(ProcessHandle handle) | |
14 : is_current_process_(false), | |
15 process_(handle) { | |
16 CHECK_NE(handle, ::GetCurrentProcess()); | |
scottmg
2014/10/14 18:51:03
why does the current process need to be handled sp
rvargas (doing something else)
2014/10/14 19:56:54
It doesn't _have_to_, but once we have a dedicated
| |
17 } | |
18 | |
19 ProcessObject::ProcessObject(RValue other) | |
20 : is_current_process_(other.object->is_current_process_), | |
21 process_(other.object->process_.Take()) { | |
22 other.object->Close(); | |
23 } | |
24 | |
25 ProcessObject& ProcessObject::operator=(RValue other) { | |
26 if (this != other.object) { | |
27 process_.Set(other.object->process_.Take()); | |
28 is_current_process_ = other.object->is_current_process_; | |
29 other.object->Close(); | |
30 } | |
31 return *this; | |
32 } | |
33 | |
34 // static | |
35 ProcessObject ProcessObject::Current() { | |
36 ProcessObject process; | |
37 process.is_current_process_ = true; | |
38 return process.Pass(); | |
39 } | |
40 | |
41 // static | |
42 bool ProcessObject::CanBackgroundProcesses() { | |
43 return true; | |
44 } | |
45 | |
46 bool ProcessObject::IsValid() const { | |
47 return process_.IsValid() || is_current(); | |
48 } | |
49 | |
50 ProcessHandle ProcessObject::Handle() const { | |
51 return is_current_process_ ? GetCurrentProcess() : process_.Get(); | |
52 } | |
53 | |
54 ProcessObject ProcessObject::Duplicate() const { | |
55 if (is_current()) | |
56 return Current(); | |
57 | |
58 ProcessHandle out_handle; | |
59 if (!IsValid() || !::DuplicateHandle(GetCurrentProcess(), | |
60 Handle(), | |
61 GetCurrentProcess(), | |
62 &out_handle, | |
63 0, | |
64 FALSE, | |
65 DUPLICATE_SAME_ACCESS)) { | |
66 return ProcessObject(); | |
67 } | |
68 return ProcessObject(out_handle); | |
69 } | |
70 | |
71 ProcessId ProcessObject::pid() const { | |
72 DCHECK(IsValid()); | |
73 return GetProcId(Handle()); | |
74 } | |
75 | |
76 bool ProcessObject::is_current() const { | |
77 return is_current_process_; | |
78 } | |
79 | |
80 void ProcessObject::Close() { | |
81 is_current_process_ = false; | |
82 if (!process_.IsValid()) | |
83 return; | |
84 | |
85 process_.Close(); | |
86 } | |
87 | |
88 void ProcessObject::Terminate(int result_code) { | |
89 DCHECK(IsValid()); | |
90 | |
91 // Call NtTerminateProcess directly, without going through the import table, | |
92 // which might have been hooked with a buggy replacement by third party | |
93 // software. http://crbug.com/81449. | |
94 HMODULE module = GetModuleHandle(L"ntdll.dll"); | |
95 typedef UINT (WINAPI *TerminateProcessPtr)(HANDLE handle, UINT code); | |
96 TerminateProcessPtr terminate_process = reinterpret_cast<TerminateProcessPtr>( | |
97 GetProcAddress(module, "NtTerminateProcess")); | |
98 terminate_process(Handle(), result_code); | |
99 } | |
100 | |
101 bool ProcessObject::IsProcessBackgrounded() const { | |
102 DCHECK(IsValid()); | |
103 DWORD priority = GetPriority(); | |
104 if (priority == 0) | |
105 return false; // Failure case. | |
106 return ((priority == BELOW_NORMAL_PRIORITY_CLASS) || | |
107 (priority == IDLE_PRIORITY_CLASS)); | |
108 } | |
109 | |
110 bool ProcessObject::SetProcessBackgrounded(bool value) { | |
111 DCHECK(IsValid()); | |
112 // Vista and above introduce a real background mode, which not only | |
113 // sets the priority class on the threads but also on the IO generated | |
114 // by it. Unfortunately it can only be set for the calling process. | |
115 DWORD priority; | |
116 if ((base::win::GetVersion() >= base::win::VERSION_VISTA) && (is_current())) { | |
117 priority = value ? PROCESS_MODE_BACKGROUND_BEGIN : | |
118 PROCESS_MODE_BACKGROUND_END; | |
119 } else { | |
120 priority = value ? BELOW_NORMAL_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS; | |
121 } | |
122 | |
123 return (::SetPriorityClass(Handle(), priority) != 0); | |
124 } | |
125 | |
126 int ProcessObject::GetPriority() const { | |
127 DCHECK(IsValid()); | |
128 return ::GetPriorityClass(Handle()); | |
129 } | |
130 | |
131 // ----------------------------------------------------------------------------- | |
132 // TODO(rvargas) crbug.com/417532: Remove Process::* | |
133 | |
134 // static | |
135 Process Process::Current() { | |
136 return Process(::GetCurrentProcess()); | |
137 } | |
138 | |
139 // static | |
140 bool Process::CanBackgroundProcesses() { | |
141 return true; | |
142 } | |
143 | |
144 ProcessId Process::pid() const { | |
145 if (process_ == 0) | |
146 return 0; | |
147 | |
148 return GetProcId(process_); | |
149 } | |
150 | |
151 bool Process::is_current() const { | |
152 return process_ == GetCurrentProcess(); | |
153 } | |
154 | |
13 void Process::Close() { | 155 void Process::Close() { |
14 if (!process_) | 156 if (!process_) |
15 return; | 157 return; |
16 | 158 |
17 // Don't call CloseHandle on a pseudo-handle. | 159 // Don't call CloseHandle on a pseudo-handle. |
18 if (process_ != ::GetCurrentProcess()) | 160 if (process_ != ::GetCurrentProcess()) |
19 ::CloseHandle(process_); | 161 ::CloseHandle(process_); |
20 | 162 |
21 process_ = NULL; | 163 process_ = NULL; |
22 } | 164 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
56 (process_ == ::GetCurrentProcess())) { | 198 (process_ == ::GetCurrentProcess())) { |
57 priority = value ? PROCESS_MODE_BACKGROUND_BEGIN : | 199 priority = value ? PROCESS_MODE_BACKGROUND_BEGIN : |
58 PROCESS_MODE_BACKGROUND_END; | 200 PROCESS_MODE_BACKGROUND_END; |
59 } else { | 201 } else { |
60 priority = value ? BELOW_NORMAL_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS; | 202 priority = value ? BELOW_NORMAL_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS; |
61 } | 203 } |
62 | 204 |
63 return (::SetPriorityClass(process_, priority) != 0); | 205 return (::SetPriorityClass(process_, priority) != 0); |
64 } | 206 } |
65 | 207 |
66 ProcessId Process::pid() const { | |
67 if (process_ == 0) | |
68 return 0; | |
69 | |
70 return GetProcId(process_); | |
71 } | |
72 | |
73 bool Process::is_current() const { | |
74 return process_ == GetCurrentProcess(); | |
75 } | |
76 | |
77 // static | |
78 Process Process::Current() { | |
79 return Process(::GetCurrentProcess()); | |
80 } | |
81 | |
82 // static | |
83 bool Process::CanBackgroundProcesses() { | |
84 return true; | |
85 } | |
86 | |
87 int Process::GetPriority() const { | 208 int Process::GetPriority() const { |
88 DCHECK(process_); | 209 DCHECK(process_); |
89 return ::GetPriorityClass(process_); | 210 return ::GetPriorityClass(process_); |
90 } | 211 } |
91 | 212 |
92 } // namespace base | 213 } // namespace base |
OLD | NEW |