OLD | NEW |
| (Empty) |
1 // Copyright 2004-2009 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 // | |
16 // Declares class Process to incapsulate win32 | |
17 // functions for creation and some manipulations of | |
18 // processes. | |
19 | |
20 #ifndef OMAHA_BASE_PROCESS_H_ | |
21 #define OMAHA_BASE_PROCESS_H_ | |
22 | |
23 #include <windows.h> | |
24 #include <psapi.h> | |
25 #include <atlstr.h> | |
26 #include <vector> | |
27 #include "base/basictypes.h" | |
28 #include "omaha/base/constants.h" | |
29 #include "omaha/base/scoped_any.h" | |
30 | |
31 namespace omaha { | |
32 | |
33 const int kMaxProcesses = 1024; | |
34 const int kMaxProcessModules = 1024; | |
35 | |
36 // Exclude mask for finding processes. | |
37 enum FindProcessesExcludeMask { | |
38 EXCLUDE_NONE = 0, | |
39 EXCLUDE_CURRENT_PROCESS = 0x1, | |
40 EXCLUDE_PROCESS_OWNED_BY_CURRENT_USER = 0x2, | |
41 EXCLUDE_PROCESS_OWNED_BY_SYSTEM = 0x4, | |
42 INCLUDE_ONLY_PROCESS_OWNED_BY_USER = 0x08, | |
43 EXCLUDE_PROCESS_COMMAND_LINE_CONTAINING_STRING = 0x10, | |
44 INCLUDE_PROCESS_COMMAND_LINE_CONTAINING_STRING = 0x20, | |
45 EXCLUDE_PARENT_PROCESS = 0x40, | |
46 }; | |
47 | |
48 // Process info used in finding descendent processes. | |
49 struct ProcessInfo { | |
50 uint32 process_id; | |
51 uint32 parent_id; | |
52 #if !SHIPPING | |
53 CString exe_file; | |
54 #endif | |
55 }; | |
56 | |
57 // Process class | |
58 class Process { | |
59 public: | |
60 // Constructor | |
61 // Init the process object with the executable name | |
62 // and if known the window class name of the process. | |
63 // If window_class_name is known it will be easy | |
64 // to stop the process just by sending messages to | |
65 // a window. | |
66 // TODO(omaha3): window_class_name is not being used. | |
67 Process(const TCHAR* name, const TCHAR* window_class_name); | |
68 | |
69 // Constructor. | |
70 // Init the process object with the process id. | |
71 explicit Process(uint32 process_id); | |
72 | |
73 // Destructor | |
74 virtual ~Process(); | |
75 | |
76 // Start the process with some command line params if any. | |
77 // If a token is provided, it will be used to start | |
78 // the process in the default desktop of the | |
79 // token's session. The caller needs to be SYSTEM in | |
80 // this case. | |
81 virtual HRESULT Start(const TCHAR* command_line_parameters, | |
82 HANDLE runas_token); | |
83 | |
84 // Restart the process with the old command line params. | |
85 HRESULT Restart(HANDLE runas_token); | |
86 | |
87 // Set shutdown event using in signaling the process watch. | |
88 void SetShutdownEvent(HANDLE shutdown_event); | |
89 | |
90 // Sets the specified priority class to the process. | |
91 bool SetPriority(uint32 priority_class) const; | |
92 | |
93 // Check if the process is running. | |
94 bool Running() const; | |
95 | |
96 // Create a job and assign the process to it. | |
97 HANDLE AssignToJob(); | |
98 | |
99 // Wait some time till the process finishes. | |
100 bool WaitUntilDead(uint32 timeout_msec); | |
101 | |
102 // Wait some time till the process and all its descendent processes finish. | |
103 bool WaitUntilAllDead(HANDLE job, | |
104 uint32 timeout_msec, | |
105 const TCHAR* path_to_exclude, | |
106 uint32* exit_code); | |
107 | |
108 // Wait until process is dead or a windows message arrives. For use in a | |
109 // message loop while waiting. | |
110 HRESULT WaitUntilDeadOrInterrupt(uint32 msec); | |
111 // Return values include CI_S_PROCESSWAIT_DEAD, CI_S_PROCESSWAIT_TIMEOUT, | |
112 // CI_S_PROCESSWAIT_MESSAGE. | |
113 | |
114 #if !SHIPPING | |
115 CString GetDebugInfo() const; | |
116 #endif | |
117 | |
118 // Return the process ID. | |
119 uint32 GetId() const; | |
120 | |
121 // Return a readable representation of the process's name. | |
122 const TCHAR *GetName() const; | |
123 | |
124 // Get win32 handle to process. | |
125 HANDLE GetHandle() const; | |
126 | |
127 // Get process exit code. | |
128 bool GetExitCode(uint32* exit_code) const; | |
129 | |
130 // can we kill the process via terminating | |
131 // some processes are not safe to terminate. | |
132 virtual bool IsTerminationAllowed() const; | |
133 | |
134 // Second, more rude method to stop the process. window_class_name was | |
135 // not given or CloseWithMessage didn't succeed. | |
136 bool Terminate(uint32 wait_for_terminate_msec); | |
137 | |
138 // Gets the parent process id. | |
139 HRESULT GetParentProcessId(uint32* parent_pid); | |
140 | |
141 // Try to get a descendant process. Return process id if found. | |
142 uint32 GetDescendantProcess(HANDLE job, | |
143 bool child_only, | |
144 bool sole_descedent, | |
145 const TCHAR* search_name, | |
146 const TCHAR* path_to_exclude); | |
147 | |
148 // Dynamically links and calls ::IsProcessInJob() in kernel32.dll. | |
149 static BOOL IsProcessInJob(HANDLE process_handle, | |
150 HANDLE job_handle, | |
151 PBOOL result); | |
152 | |
153 // Try to get all matching descendant processes. | |
154 HRESULT GetAllDescendantProcesses( | |
155 HANDLE job, | |
156 bool child_only, | |
157 const TCHAR* search_name, | |
158 const TCHAR* path_to_exclude, | |
159 std::vector<ProcessInfo>* descendant_proc_ids); | |
160 | |
161 // Finds the processes based on passed criteria. | |
162 static HRESULT FindProcesses(uint32 exclude_mask, | |
163 const TCHAR* search_name, | |
164 bool search_main_executable_only, | |
165 std::vector<uint32>* process_ids_found); | |
166 | |
167 // Find processes which loads the specified exe/dll. Uses the user_sid only | |
168 // if the INCLUDE_ONLY_PROCESS_OWNED_BY_USER flag has been set. | |
169 // The command_line is only used when | |
170 // EXCLUDE_PROCESS_COMMAND_LINE_CONTAINING_STRING is set. | |
171 static HRESULT FindProcesses(uint32 exclude_mask, | |
172 const TCHAR* search_name, | |
173 bool search_main_executable_only, | |
174 const CString& user_sid, | |
175 const std::vector<CString>& command_line, | |
176 std::vector<uint32>* process_ids_found); | |
177 | |
178 // Find processes with the specified criteria running in specific session. | |
179 static HRESULT FindProcessesInSession(DWORD session_id, | |
180 uint32 exclude_mask, | |
181 const TCHAR* search_name, | |
182 bool search_main_executable_only, | |
183 const CString& user_sid, | |
184 const std::vector<CString>& cmd_lines, | |
185 std::vector<uint32>* process_ids_found); | |
186 | |
187 // Is the process using the specified exe/dll. | |
188 static bool IsProcessUsingExeOrDll(uint32 process_id, | |
189 const TCHAR* search_name, | |
190 bool search_main_executable_only); | |
191 | |
192 // Obtain the process ID from a hProcess HANDLE. | |
193 static ULONG GetProcessIdFromHandle(HANDLE hProcess); | |
194 | |
195 // Get the fully qualified path of the executable file for a process. | |
196 static HRESULT GetExecutablePath(uint32 process_id, CString *exe_path); | |
197 | |
198 // Get the command line of a process. | |
199 static HRESULT GetCommandLine(uint32 process_id, CString* cmd_line); | |
200 | |
201 // Get the process owner. | |
202 static HRESULT GetProcessOwner(uint32 pid, CString* owner_sid); | |
203 | |
204 // Creates an impersonation token for the user running process_id. | |
205 // The caller is responsible for closing the returned handle. | |
206 static HRESULT GetImpersonationToken(DWORD process_id, HANDLE* user_token); | |
207 | |
208 // Returns user token handles for the users currently running the named task. | |
209 // maximum_users specifies the maximun number of handles to be retured. | |
210 // The actual number filled is returned. | |
211 static HRESULT GetUsersOfProcesses(const TCHAR* task_name, | |
212 int maximum_users, | |
213 scoped_handle users[], | |
214 int* number_of_users); | |
215 | |
216 // Gets the on disk path from where the process image is loaded. | |
217 static HRESULT GetImagePath(const CString& process_name, | |
218 const CString& user_sid, | |
219 CString* path); | |
220 | |
221 // Returns if the process is running under WOW64. | |
222 static bool IsWow64(uint32 pid); | |
223 | |
224 public: | |
225 // How many times the process can be restarted in case it crashes. | |
226 virtual uint32 GetMaxNumberOfRestarts() const; | |
227 | |
228 // Maximum amount of memory process is allowed to use before it's killed. | |
229 // Default of 0 means unlimited. | |
230 virtual uint32 GetMaxMemory() const; | |
231 | |
232 // Have we exceeded the number of maximum restarting. | |
233 bool AllowedToRestart() const; | |
234 | |
235 // In case of crash, how soon to restart. | |
236 virtual uint32 GetRestartInterval() const; | |
237 | |
238 // The idea is the following. Each process has maximum number of restarts. | |
239 // As soon as the process reaches that number of restarts in should no longer | |
240 // be restarted unless the time window in which the process was crashing is | |
241 // more than the value returned by this function. For example: | |
242 // Process X returns 3 from the function GetMaxNumberOfRestarts. | |
243 // The same process returns 30*1000*60 (30 minutes) from | |
244 // GetTimeWindowForCrashes if process X crashed more than 3 times in 30 | |
245 // minutes it will not be restarted. if it took more than 30 minutes for | |
246 // process X to crash more than 3 times - internal counters for number of | |
247 // crashes will be reset and the process will be happily restarted. | |
248 // Each derived process can override this function to return its own time | |
249 // window for crashes. | |
250 // Default implementation returns INFINITE which means that this is not time | |
251 // based at all, if the process crashed more than the value returned by | |
252 // GetMaxNumberOfRestarts it will not be restarted no matter how long it took. | |
253 virtual uint32 GetTimeWindowForCrashes() const; | |
254 | |
255 // Sets the main window of all process instances to the foreground. | |
256 static HRESULT MakeProcessWindowForeground(const CString& executable); | |
257 | |
258 private: | |
259 mutable uint32 number_of_restarts_; | |
260 CString command_line_; | |
261 CString command_line_parameters_; | |
262 CString window_class_name_; | |
263 CString name_; | |
264 scoped_process process_; | |
265 uint32 process_id_; | |
266 mutable uint32 time_of_start_; | |
267 mutable uint32 exit_code_; | |
268 HANDLE shutdown_event_; | |
269 | |
270 // Helper function to wait till the process and all its descendent processes | |
271 // finish. | |
272 bool InternalWaitUntilAllDead(HANDLE job, | |
273 uint32 timeout_msec, | |
274 const TCHAR* path_to_exclude, | |
275 uint32* exit_code); | |
276 | |
277 // Check if the process is running with a specified path. | |
278 static bool IsProcessRunningWithPath(uint32 process_id, const TCHAR* path); | |
279 | |
280 // Checks if the command line of the process has been specified as one to | |
281 // ignore. | |
282 static bool IsStringPresentInList(const CString& process_command_line, | |
283 const std::vector<CString>& list); | |
284 | |
285 | |
286 // Helper function to get long path name. | |
287 static HRESULT GetLongPathName(const TCHAR* short_name, CString* long_name); | |
288 | |
289 // Helper for Process::IsProcessUsingExeOrDll(). Use GetProcessImageFileName | |
290 // to get the filename, and match against search_name. | |
291 static bool IsProcImageMatch(HANDLE proc_handle, | |
292 const TCHAR* search_name, | |
293 bool is_fully_qualified_name); | |
294 | |
295 // Dynamically links and calls ::GetProcessImageFileName() in psapi.dll. | |
296 static DWORD GetProcessImageFileName(HANDLE proc_handle, | |
297 LPTSTR image_file, | |
298 DWORD file_size); | |
299 | |
300 // Helper for Process::IsProcessUsingExeOrDll(). | |
301 // Is there a match between the module and the specified exe/dll? | |
302 static bool IsModuleMatchingExeOrDll(const TCHAR* module_name, | |
303 const TCHAR* search_name, | |
304 bool is_fully_qualified_name); | |
305 | |
306 #if !SHIPPING | |
307 CString debug_info_; | |
308 #endif | |
309 DISALLOW_EVIL_CONSTRUCTORS(Process); | |
310 }; | |
311 | |
312 } // namespace omaha | |
313 | |
314 #endif // OMAHA_BASE_PROCESS_H_ | |
OLD | NEW |