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()); |
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 |