| 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 |