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 Process::Process(ProcessHandle handle) | |
14 : is_current_process_(false), | |
15 process_(handle) { | |
16 CHECK_NE(handle, ::GetCurrentProcess()); | |
17 } | |
18 | |
19 Process::Process(RValue other) | |
20 : is_current_process_(other.object->is_current_process_), | |
21 process_(other.object->process_.Take()) { | |
22 other.object->Close(); | |
23 } | |
24 | |
25 Process& Process::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 Process Process::Current() { | |
36 Process process; | |
37 process.is_current_process_ = true; | |
38 return process.Pass(); | |
39 } | |
40 | |
41 // static | |
42 bool Process::CanBackgroundProcesses() { | |
43 return true; | |
44 } | |
45 | |
46 bool Process::IsValid() const { | |
47 return process_.IsValid() || is_current(); | |
48 } | |
49 | |
50 ProcessHandle Process::Handle() const { | |
51 return is_current_process_ ? GetCurrentProcess() : process_.Get(); | |
52 } | |
53 | |
54 Process Process::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 Process(); | |
67 } | |
68 return Process(out_handle); | |
69 } | |
70 | |
71 ProcessId Process::pid() const { | |
72 DCHECK(IsValid()); | |
73 return GetProcId(Handle()); | |
74 } | |
75 | |
76 bool Process::is_current() const { | |
77 return is_current_process_; | |
78 } | |
79 | |
13 void Process::Close() { | 80 void Process::Close() { |
14 if (!process_) | 81 is_current_process_ = false; |
82 if (!process_.IsValid()) | |
15 return; | 83 return; |
16 | 84 |
17 // Don't call CloseHandle on a pseudo-handle. | 85 process_.Close(); |
18 if (process_ != ::GetCurrentProcess()) | |
19 ::CloseHandle(process_); | |
20 | |
21 process_ = NULL; | |
22 } | 86 } |
23 | 87 |
24 void Process::Terminate(int result_code) { | 88 void Process::Terminate(int result_code) { |
25 if (!process_) | 89 DCHECK(IsValid()); |
Lei Zhang
2014/10/16 02:50:08
Can you give some reassurances that these DCHECKs
rvargas (doing something else)
2014/10/16 19:06:10
The DCHECKs are going through internal state only
| |
26 return; | |
27 | 90 |
28 // Call NtTerminateProcess directly, without going through the import table, | 91 // Call NtTerminateProcess directly, without going through the import table, |
29 // which might have been hooked with a buggy replacement by third party | 92 // which might have been hooked with a buggy replacement by third party |
30 // software. http://crbug.com/81449. | 93 // software. http://crbug.com/81449. |
31 HMODULE module = GetModuleHandle(L"ntdll.dll"); | 94 HMODULE module = GetModuleHandle(L"ntdll.dll"); |
32 typedef UINT (WINAPI *TerminateProcessPtr)(HANDLE handle, UINT code); | 95 typedef UINT (WINAPI *TerminateProcessPtr)(HANDLE handle, UINT code); |
33 TerminateProcessPtr terminate_process = reinterpret_cast<TerminateProcessPtr>( | 96 TerminateProcessPtr terminate_process = reinterpret_cast<TerminateProcessPtr>( |
34 GetProcAddress(module, "NtTerminateProcess")); | 97 GetProcAddress(module, "NtTerminateProcess")); |
35 terminate_process(process_, result_code); | 98 terminate_process(Handle(), result_code); |
36 } | 99 } |
37 | 100 |
38 bool Process::IsProcessBackgrounded() const { | 101 bool Process::IsProcessBackgrounded() const { |
39 if (!process_) | 102 DCHECK(IsValid()); |
40 return false; // Failure case. | |
41 DWORD priority = GetPriority(); | 103 DWORD priority = GetPriority(); |
42 if (priority == 0) | 104 if (priority == 0) |
43 return false; // Failure case. | 105 return false; // Failure case. |
44 return ((priority == BELOW_NORMAL_PRIORITY_CLASS) || | 106 return ((priority == BELOW_NORMAL_PRIORITY_CLASS) || |
45 (priority == IDLE_PRIORITY_CLASS)); | 107 (priority == IDLE_PRIORITY_CLASS)); |
46 } | 108 } |
47 | 109 |
48 bool Process::SetProcessBackgrounded(bool value) { | 110 bool Process::SetProcessBackgrounded(bool value) { |
49 if (!process_) | 111 DCHECK(IsValid()); |
50 return false; | |
51 // Vista and above introduce a real background mode, which not only | 112 // Vista and above introduce a real background mode, which not only |
52 // sets the priority class on the threads but also on the IO generated | 113 // sets the priority class on the threads but also on the IO generated |
53 // by it. Unfortunately it can only be set for the calling process. | 114 // by it. Unfortunately it can only be set for the calling process. |
54 DWORD priority; | 115 DWORD priority; |
55 if ((base::win::GetVersion() >= base::win::VERSION_VISTA) && | 116 if ((base::win::GetVersion() >= base::win::VERSION_VISTA) && (is_current())) { |
56 (process_ == ::GetCurrentProcess())) { | |
57 priority = value ? PROCESS_MODE_BACKGROUND_BEGIN : | 117 priority = value ? PROCESS_MODE_BACKGROUND_BEGIN : |
58 PROCESS_MODE_BACKGROUND_END; | 118 PROCESS_MODE_BACKGROUND_END; |
59 } else { | 119 } else { |
60 priority = value ? BELOW_NORMAL_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS; | 120 priority = value ? BELOW_NORMAL_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS; |
61 } | 121 } |
62 | 122 |
63 return (::SetPriorityClass(process_, priority) != 0); | 123 return (::SetPriorityClass(Handle(), priority) != 0); |
64 } | |
65 | |
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 } | 124 } |
86 | 125 |
87 int Process::GetPriority() const { | 126 int Process::GetPriority() const { |
88 DCHECK(process_); | 127 DCHECK(IsValid()); |
89 return ::GetPriorityClass(process_); | 128 return ::GetPriorityClass(Handle()); |
90 } | 129 } |
91 | 130 |
92 } // namespace base | 131 } // namespace base |
OLD | NEW |