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
3 // found in the LICENSE file.
5 #include "base/process/process.h"
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/process/kill.h"
10 #include "base/win/windows_version.h"
14 DWORD kBasicProcessAccess
=
15 PROCESS_TERMINATE
| PROCESS_QUERY_INFORMATION
| SYNCHRONIZE
;
21 Process::Process(ProcessHandle handle
)
22 : is_current_process_(false),
24 CHECK_NE(handle
, ::GetCurrentProcess());
27 Process::Process(RValue other
)
28 : is_current_process_(other
.object
->is_current_process_
),
29 process_(other
.object
->process_
.Take()) {
30 other
.object
->Close();
33 Process
& Process::operator=(RValue other
) {
34 if (this != other
.object
) {
35 process_
.Set(other
.object
->process_
.Take());
36 is_current_process_
= other
.object
->is_current_process_
;
37 other
.object
->Close();
43 Process
Process::Current() {
45 process
.is_current_process_
= true;
46 return process
.Pass();
50 Process
Process::OpenWithExtraPriviles(ProcessId pid
) {
51 DWORD access
= kBasicProcessAccess
| PROCESS_DUP_HANDLE
| PROCESS_VM_READ
;
52 ProcessHandle handle
= ::OpenProcess(access
, FALSE
, pid
);
53 return Process(handle
);
57 Process
Process::OpenWithAccess(ProcessId pid
, DWORD desired_access
) {
58 return Process(::OpenProcess(desired_access
, FALSE
, pid
));
62 Process
Process::DeprecatedGetProcessFromHandle(ProcessHandle handle
) {
63 DCHECK_NE(handle
, ::GetCurrentProcess());
64 ProcessHandle out_handle
;
65 if (!::DuplicateHandle(GetCurrentProcess(), handle
,
66 GetCurrentProcess(), &out_handle
,
67 0, FALSE
, DUPLICATE_SAME_ACCESS
)) {
70 return Process(out_handle
);
74 bool Process::CanBackgroundProcesses() {
78 bool Process::IsValid() const {
79 return process_
.IsValid() || is_current();
82 ProcessHandle
Process::Handle() const {
83 return is_current_process_
? GetCurrentProcess() : process_
.Get();
86 Process
Process::Duplicate() const {
90 ProcessHandle out_handle
;
91 if (!IsValid() || !::DuplicateHandle(GetCurrentProcess(),
97 DUPLICATE_SAME_ACCESS
)) {
100 return Process(out_handle
);
103 ProcessId
Process::Pid() const {
105 return GetProcId(Handle());
108 bool Process::is_current() const {
109 return is_current_process_
;
112 void Process::Close() {
113 is_current_process_
= false;
114 if (!process_
.IsValid())
120 void Process::Terminate(int result_code
) {
123 // Call NtTerminateProcess directly, without going through the import table,
124 // which might have been hooked with a buggy replacement by third party
125 // software. http://crbug.com/81449.
126 HMODULE module
= GetModuleHandle(L
"ntdll.dll");
127 typedef UINT (WINAPI
*TerminateProcessPtr
)(HANDLE handle
, UINT code
);
128 TerminateProcessPtr terminate_process
= reinterpret_cast<TerminateProcessPtr
>(
129 GetProcAddress(module
, "NtTerminateProcess"));
130 terminate_process(Handle(), result_code
);
133 bool Process::WaitForExit(int* exit_code
) {
134 return WaitForExitWithTimeout(TimeDelta::FromMilliseconds(INFINITE
),
138 bool Process::WaitForExitWithTimeout(TimeDelta timeout
, int* exit_code
) {
139 // TODO(rvargas) crbug.com/417532: Move the implementation here.
140 if (timeout
> TimeDelta::FromMilliseconds(INFINITE
))
141 timeout
= TimeDelta::FromMilliseconds(INFINITE
);
142 return base::WaitForExitCodeWithTimeout(Handle(), exit_code
, timeout
);
145 bool Process::IsProcessBackgrounded() const {
147 DWORD priority
= GetPriority();
149 return false; // Failure case.
150 return ((priority
== BELOW_NORMAL_PRIORITY_CLASS
) ||
151 (priority
== IDLE_PRIORITY_CLASS
));
154 bool Process::SetProcessBackgrounded(bool value
) {
156 // Vista and above introduce a real background mode, which not only
157 // sets the priority class on the threads but also on the IO generated
158 // by it. Unfortunately it can only be set for the calling process.
160 if ((base::win::GetVersion() >= base::win::VERSION_VISTA
) && (is_current())) {
161 priority
= value
? PROCESS_MODE_BACKGROUND_BEGIN
:
162 PROCESS_MODE_BACKGROUND_END
;
164 priority
= value
? BELOW_NORMAL_PRIORITY_CLASS
: NORMAL_PRIORITY_CLASS
;
167 return (::SetPriorityClass(Handle(), priority
) != 0);
170 int Process::GetPriority() const {
172 return ::GetPriorityClass(Handle());