Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: installer/src/installer-lib/process.cpp

Issue 5992177905696768: Issue #1186 - Rename symbols defined in 'installer-lib' (Closed)
Patch Set: fixed issues; rebased; new fixes from rebase Created June 19, 2015, 4:09 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « installer/src/installer-lib/process.h ('k') | installer/src/installer-lib/property.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #include <stdexcept> 1 #include <stdexcept>
2 #include <functional> 2 #include <functional>
3 #include <wctype.h> 3 #include <wctype.h>
4 // <thread> is C++11, but implemented in VS2012 4 // <thread> is C++11, but implemented in VS2012
5 #include <thread> 5 #include <thread>
6 6
7 #include "installer-lib.h" 7 #include "installer-lib.h"
8 #include "process.h" 8 #include "process.h"
9 #include "handle.h" 9 #include "handle.h"
10 #include "session.h" 10 #include "session.h"
11 11
12 //------------------------------------------------------- 12 //-------------------------------------------------------
13 //------------------------------------------------------- 13 //-------------------------------------------------------
14 typedef int (__stdcall *IsImmersiveDynamicFunc)(HANDLE); 14 typedef int (__stdcall *IsImmersiveDynamicFunc)(HANDLE);
15 bool process_by_any_exe_not_immersive::operator()( const PROCESSENTRY32W & proce ss ) 15 bool ProcessByAnyExeNotImmersive::operator()( const PROCESSENTRY32W & process )
16 { 16 {
17 // If the name is not found in our list, it's filtered out 17 // If the name is not found in our list, it's filtered out
18 if (processNames.find(process.szExeFile) == processNames.end()) return false; 18 if (processNames.find(process.szExeFile) == processNames.end()) return false;
19 19
20 // Make sure the process is still alive 20 // Make sure the process is still alive
21 HANDLE tmpHandle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, process.th32P rocessID); 21 HANDLE tmpHandle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, process.th32P rocessID);
22 if (tmpHandle == NULL) return false; 22 if (tmpHandle == NULL) return false;
23 Windows_Handle procHandle(tmpHandle); 23 WindowsHandle procHandle(tmpHandle);
24 DWORD exitCode; 24 DWORD exitCode;
25 if (!GetExitCodeProcess(procHandle, &exitCode)) return false; 25 if (!GetExitCodeProcess(procHandle, &exitCode)) return false;
26 if (exitCode != STILL_ACTIVE) return false; 26 if (exitCode != STILL_ACTIVE) return false;
27 27
28 // Check if this is a Windows Store app process (we don't care for IE in Moder n UI) 28 // Check if this is a Windows Store app process (we don't care for IE in Moder n UI)
29 HMODULE user32Dll = LoadLibrary(L"user32.dll"); 29 HMODULE user32Dll = LoadLibrary(L"user32.dll");
30 if (!user32Dll) return true; 30 if (!user32Dll) return true;
31 IsImmersiveDynamicFunc IsImmersiveDynamicCall = (IsImmersiveDynamicFunc)GetPro cAddress(user32Dll, "IsImmersiveProcess"); 31 IsImmersiveDynamicFunc IsImmersiveDynamicCall = (IsImmersiveDynamicFunc)GetPro cAddress(user32Dll, "IsImmersiveProcess");
32 if (!IsImmersiveDynamicCall) return true; 32 if (!IsImmersiveDynamicCall) return true;
33 return !IsImmersiveDynamicCall(procHandle); 33 return !IsImmersiveDynamicCall(procHandle);
34 } 34 }
35 35
36 //------------------------------------------------------- 36 //-------------------------------------------------------
37 // creator_process 37 // CreatorProcess
38 //------------------------------------------------------- 38 //-------------------------------------------------------
39 DWORD creator_process( HWND window ) 39 DWORD CreatorProcess( HWND window )
40 { 40 {
41 DWORD pid ; 41 DWORD pid ;
42 DWORD r = GetWindowThreadProcessId( window, & pid ) ; 42 DWORD r = GetWindowThreadProcessId( window, & pid ) ;
43 if ( r == 0 ) 43 if ( r == 0 )
44 { 44 {
45 // Assert GetWindowThreadProcessId returned an error 45 // Assert GetWindowThreadProcessId returned an error
46 // If the window handle is invalid, we end up here. 46 // If the window handle is invalid, we end up here.
47 throw windows_api_error( "GetWindowThreadProcessId", r ) ; 47 throw WindowsApiError( "GetWindowThreadProcessId", r ) ;
48 } 48 }
49 return pid ; 49 return pid ;
50 } 50 }
51 51
52 //------------------------------------------------------- 52 //-------------------------------------------------------
53 // send_message, send_endsession_messages 53 // SendMessageAction, SendEndsessionMessagesAction
54 //------------------------------------------------------- 54 //-------------------------------------------------------
55 /** 55 /**
56 * Default process exit wait time (per message) 5000 ms 56 * Default process exit wait time (per message) 5000 ms
57 * 57 *
58 * 5 seconds is time that the system will wait before it considers a process non- responsive. 58 * 5 seconds is time that the system will wait before it considers a process non- responsive.
59 */ 59 */
60 static const unsigned int timeout = 5000 ; // milliseconds 60 static const unsigned int timeout = 5000 ; // milliseconds
61 61
62 /** 62 /**
63 * An function object to process the results of sending window messages in send_m essage. 63 * An function object to process the results of sending window messages in SendMe ssageAction.
64 * 64 *
65 * We are using send_message within a system iteration over windows. 65 * We are using SendMessageAction within a system iteration over windows.
66 * The system has its own convention for continuing/breaking the iteration. 66 * The system has its own convention for continuing/breaking the iteration.
67 * This convention is assured consistently in send_message, which also provides d efault behavior. 67 * This convention is assured consistently in SendMessageAction, which also provi des default behavior.
68 * This class provides the base for any variation from the default behavior. 68 * This class provides the base for any variation from the default behavior.
69 */ 69 */
70 struct message_accumulator 70 struct MessageAccumulator
71 : public std::binary_function< DWORD_PTR, bool, bool > 71 : public std::binary_function< DWORD_PTR, bool, bool >
72 { 72 {
73 virtual result_type operator()( first_argument_type result, second_argument_ty pe return_value ) = 0 ; 73 virtual result_type operator()( first_argument_type result, second_argument_ty pe returnValue ) = 0 ;
74 virtual ~message_accumulator() {} ; 74 virtual ~MessageAccumulator() {} ;
75 } ; 75 } ;
76 76
77 /** 77 /**
78 * Iteration action to send a message to a window and accumulate results. 78 * Iteration action to send a message to a window and accumulate results.
79 * 79 *
80 * An error sending the message is not a failure for the function a whole. 80 * An error sending the message is not a failure for the function a whole.
81 * The goal is to close the process, and if the window is no longer present, then the process may have already closed. 81 * The goal is to close the process, and if the window is no longer present, then the process may have already closed.
82 * Therefore, we're ignoring both the return value and the result. 82 * Therefore, we're ignoring both the return value and the result.
83 */ 83 */
84 class send_message 84 class SendMessageAction
85 { 85 {
86 UINT message ; ///< Message type for windows message 86 UINT message ; ///< Message type for windows message
87 WPARAM p1 ; ///< Generic parameter 1 for windows message 87 WPARAM p1 ; ///< Generic parameter 1 for windows message
88 LPARAM p2 ; ///< Generic parameter 2 for windows message 88 LPARAM p2 ; ///< Generic parameter 2 for windows message
89 message_accumulator * f ;» ///< Processor for results of sending the messag e. 89 MessageAccumulator * f ;» ///< Processor for results of sending the messag e.
90 90
91 public: 91 public:
92 /** 92 /**
93 * Full contructor gathers message parameters and a message accumulator. 93 * Full contructor gathers message parameters and a message accumulator.
94 */ 94 */
95 send_message( UINT message, WPARAM p1, LPARAM p2, message_accumulator & f ) 95 SendMessageAction( UINT message, WPARAM p1, LPARAM p2, MessageAccumulator & f )
96 : message( message ), p1( p1 ), p2( p2 ), f( & f ) 96 : message( message ), p1( p1 ), p2( p2 ), f( & f )
97 {} 97 {}
98 98
99 /** 99 /**
100 * Abbreviated contructor gathers only message parameters. 100 * Abbreviated contructor gathers only message parameters.
101 * The message accumulator is absent. 101 * The message accumulator is absent.
102 */ 102 */
103 send_message( UINT message, WPARAM p1, LPARAM p2 ) 103 SendMessageAction( UINT message, WPARAM p1, LPARAM p2 )
104 : message( message ), p1( p1 ), p2( p2 ), f( 0 ) 104 : message( message ), p1( p1 ), p2( p2 ), f( 0 )
105 {} 105 {}
106 106
107 /* 107 /*
108 * Enumeration function applied to each window. 108 * Enumeration function applied to each window.
109 */ 109 */
110 bool operator()( HWND window ) 110 bool operator()( HWND window )
111 { 111 {
112 DWORD_PTR result ; 112 DWORD_PTR result ;
113 LRESULT rv = SendMessageTimeoutW( window, message, p1, p2, SMTO_BLOCK, timeo ut, & result ) ; 113 LRESULT rv = SendMessageTimeoutW( window, message, p1, p2, SMTO_BLOCK, timeo ut, & result ) ;
114 /* 114 /*
115 * If we have no message accumulator, the default behavior is to iterate ever ything. 115 * If we have no message accumulator, the default behavior is to iterate ever ything.
116 * If we do have one, we delegate to it the decision whether to break or to c ontinue. 116 * If we do have one, we delegate to it the decision whether to break or to c ontinue.
117 */ 117 */
118 if ( ! f ) 118 if ( ! f )
119 { 119 {
120 return true ; 120 return true ;
121 } 121 }
122 return ( * f )( result, (rv != 0) ) ; 122 return ( * f )( result, (rv != 0) ) ;
123 } 123 }
124 } ; 124 } ;
125 125
126 /** 126 /**
127 * Send WM_QUERYENDSESSION and WM_ENDSESSION to a window. 127 * Send WM_QUERYENDSESSION and WM_ENDSESSION to a window.
128 * 128 *
129 * This window processor tries to shut down each application individually. 129 * This window processor tries to shut down each application individually.
130 * The alternative, gathering all the query results first and only then ending se ssions, cannot be done with a single window enumeration. 130 * The alternative, gathering all the query results first and only then ending se ssions, cannot be done with a single window enumeration.
131 */ 131 */
132 class send_endsession_messages 132 class SendEndsessionMessagesAction
133 { 133 {
134 public: 134 public:
135 /* 135 /*
136 * Enumeration function applied to each window. 136 * Enumeration function applied to each window.
137 */ 137 */
138 bool operator()( HWND window ) 138 bool operator()( HWND window )
139 { 139 {
140 DWORD_PTR result ; 140 DWORD_PTR result ;
141 if ( ! SendMessageTimeoutW( window, WM_QUERYENDSESSION, 0, ENDSESSION_CLOSEA PP, SMTO_BLOCK, timeout, & result ) ) 141 if ( ! SendMessageTimeoutW( window, WM_QUERYENDSESSION, 0, ENDSESSION_CLOSEA PP, SMTO_BLOCK, timeout, & result ) )
142 { 142 {
143 // Assert sending the message failed 143 // Assert sending the message failed
144 // Ignore failure, just as with send_message(). 144 // Ignore failure, just as with SendMessageAction().
145 return true ; 145 return true ;
146 } 146 }
147 // Assert result is FALSE if the process has refused notice that it should s hut down. 147 // Assert result is FALSE if the process has refused notice that it should s hut down.
148 if ( ! result ) 148 if ( ! result )
149 { 149 {
150 /* 150 /*
151 * Returning false terminates iteration over windows. 151 * Returning false terminates iteration over windows.
152 * Since this process is refusing to shut down, we can't close all the proc esses and the operation fails. 152 * Since this process is refusing to shut down, we can't close all the proc esses and the operation fails.
153 */ 153 */
154 return false ; 154 return false ;
155 } 155 }
156 SendMessageTimeoutW( window, WM_ENDSESSION, 0, ENDSESSION_CLOSEAPP, SMTO_BLO CK, timeout, 0 ) ; 156 SendMessageTimeoutW( window, WM_ENDSESSION, 0, ENDSESSION_CLOSEAPP, SMTO_BLO CK, timeout, 0 ) ;
157 return true ; 157 return true ;
158 } 158 }
159 } ; 159 } ;
160 160
161 /** 161 /**
162 * Accumulator for query-endsession message. 162 * Accumulator for query-endsession message.
163 * 163 *
164 * Implements a conditional-conjunction of the query results. 164 * Implements a conditional-conjunction of the query results.
165 * All answers must be true in order for this result to be true, 165 * All answers must be true in order for this result to be true,
166 * and the calculation is terminated at the first answer 'false'. 166 * and the calculation is terminated at the first answer 'false'.
167 * As usual, errors sending messages are ignored. 167 * As usual, errors sending messages are ignored.
168 */ 168 */
169 struct endsession_accumulator : 169 struct EndsessionAccumulator :
170 public message_accumulator 170 public MessageAccumulator
171 { 171 {
172 bool permit_end_session ; ///< Accumulator variable yields final result. 172 bool permitEndSession ; ///< Accumulator variable yields final result.
173 173
174 /** 174 /**
175 * Enumeration function applied to each window. 175 * Enumeration function applied to each window.
176 */ 176 */
177 bool operator()( DWORD_PTR result, bool return_value ) 177 bool operator()( DWORD_PTR result, bool returnValue )
178 { 178 {
179 if ( ( ! return_value ) || result ) 179 if ( ( ! returnValue ) || result )
180 { 180 {
181 // 1. If the result is true, then the process will permit WM_ENDSESSION 181 // 1. If the result is true, then the process will permit WM_ENDSESSION
182 // 2. An error sending the message counts as "no new information" 182 // 2. An error sending the message counts as "no new information"
183 return true ; 183 return true ;
184 } 184 }
185 // The first false is the result of the calculation. 185 // The first false is the result of the calculation.
186 // The second false means to terminate enumeration early. 186 // The second false means to terminate enumeration early.
187 permit_end_session = false ; 187 permitEndSession = false ;
188 return false ; 188 return false ;
189 } 189 }
190 190
191 /** 191 /**
192 * Ordinary constructor. 192 * Ordinary constructor.
193 */ 193 */
194 endsession_accumulator() 194 EndsessionAccumulator()
195 : permit_end_session( true ) 195 : permitEndSession( true )
196 {} 196 {}
197 } ; 197 } ;
198 198
199 //------------------------------------------------------- 199 //-------------------------------------------------------
200 // ProcessCloser 200 // ProcessCloser
201 //------------------------------------------------------- 201 //-------------------------------------------------------
202 /** 202 /**
203 * Shut down all the processes in the pid_list. 203 * Shut down all the processes in the pidSet.
204 * 204 *
205 * The method used here uses blocking system calls to send messages to target pro cesses. 205 * The method used here uses blocking system calls to send messages to target pro cesses.
206 * Message processing delays, therefore, are sequential and the total delay is th eir sum. 206 * Message processing delays, therefore, are sequential and the total delay is th eir sum.
207 * Windows has non-blocking message calls available, and using a multi-threaded i mplementation would shorten that delay. 207 * Windows has non-blocking message calls available, and using a multi-threaded i mplementation would shorten that delay.
208 * The code, hwoever, is significantly simpler without multi-threading. 208 * The code, hwoever, is significantly simpler without multi-threading.
209 * The present use of this method is not closing dozens of applications, so delay performance is not critical. 209 * The present use of this method is not closing dozens of applications, so delay performance is not critical.
210 * 210 *
211 * \return 211 * \return
212 * The negation of is_running. 212 * The negation of IsRunning().
213 * If is_running() was true at the beginning, then this function will have run refresh() before returning. 213 * If IsRunning() was true at the beginning, then this function will have run r efresh() before returning.
214 * 214 *
215 * \sa 215 * \sa
216 * - MSDN [WM_QUERYENDSESSION message](http://msdn.microsoft.com/en-us/library/ windows/desktop/aa376890%28v=vs.85%29.aspx) 216 * - MSDN [WM_QUERYENDSESSION message](http://msdn.microsoft.com/en-us/library/ windows/desktop/aa376890%28v=vs.85%29.aspx)
217 * - MSDN [WM_ENDSESSION message](http://msdn.microsoft.com/en-us/library/windo ws/desktop/aa376889%28v=vs.85%29.aspx) 217 * - MSDN [WM_ENDSESSION message](http://msdn.microsoft.com/en-us/library/windo ws/desktop/aa376889%28v=vs.85%29.aspx)
218 */ 218 */
219 bool ProcessCloser::ShutDown(ImmediateSession& session) 219 bool ProcessCloser::ShutDown(ImmediateSession& session)
220 { 220 {
221 /* 221 /*
222 * If we're not running, we don't need to shut down. 222 * If we're not running, we don't need to shut down.
223 */ 223 */
224 if ( ! IsRunning() ) 224 if ( ! IsRunning() )
225 { 225 {
226 return true ; 226 return true ;
227 } 227 }
228 228
229 /* 229 /*
230 * Shutting down is a structure as an escalating series of attempts to shut dow n. 230 * Shutting down is a structure as an escalating series of attempts to shut dow n.
231 * After each one, we wait to see if the shut down has completed. 231 * After each one, we wait to see if the shut down has completed.
232 * Even though we're using a blocking call to send messages, applications need not block before exiting. 232 * Even though we're using a blocking call to send messages, applications need not block before exiting.
233 * Internet Explorer, in particular, does not. 233 * Internet Explorer, in particular, does not.
234 * 234 *
235 * Note that termination occurs inside the default case within the switch state ment 235 * Note that termination occurs inside the default case within the switch state ment
236 */ 236 */
237 for ( unsigned int stage = 1 ; ; ++ stage ) 237 for ( unsigned int stage = 1 ; ; ++ stage )
238 { 238 {
239 // Assert is_running() 239 // Assert IsRunning()
240 switch( stage ) 240 switch( stage )
241 { 241 {
242 case 1 : 242 case 1 :
243 /* 243 /*
244 * Send WM_QUERYENDSESSION to every admissible window. 244 * Send WM_QUERYENDSESSION to every admissible window.
245 * Send WM_ENDSESSION if all processes are ready to shut down. 245 * Send WM_ENDSESSION if all processes are ready to shut down.
246 * We try this technique first, since this allows an application to restore its application state when it starts up again. 246 * We try this technique first, since this allows an application to restore its application state when it starts up again.
247 */ 247 */
248 { 248 {
249 endsession_accumulator acc ; 249 EndsessionAccumulator acc ;
250 send_message m1( WM_QUERYENDSESSION, 0, ENDSESSION_CLOSEAPP, acc ) ; 250 SendMessageAction m1( WM_QUERYENDSESSION, 0, ENDSESSION_CLOSEAPP, acc ) ;
251 iterate_our_windows( m1 ) ; 251 IterateOurWindows( m1 ) ;
252 252
253 if ( acc.permit_end_session ) 253 if ( acc.permitEndSession )
254 { 254 {
255 send_message m2( WM_ENDSESSION, 0, ENDSESSION_CLOSEAPP ) ; 255 SendMessageAction m2( WM_ENDSESSION, 0, ENDSESSION_CLOSEAPP ) ;
256 iterate_our_windows( m2 ) ; 256 IterateOurWindows( m2 ) ;
257 } 257 }
258 } 258 }
259 break ; 259 break ;
260 260
261 case 2 : 261 case 2 :
262 { 262 {
263 /* 263 /*
264 * Send WM_QUERYENDSESSION and WM_ENDSESSION to every admissible window s ingly, not accumulating results. 264 * Send WM_QUERYENDSESSION and WM_ENDSESSION to every admissible window s ingly, not accumulating results.
265 */ 265 */
266 send_endsession_messages m ; 266 SendEndsessionMessagesAction m ;
267 iterate_our_windows( m ) ; 267 IterateOurWindows( m ) ;
268 } 268 }
269 break ; 269 break ;
270 270
271 case 3 : 271 case 3 :
272 { 272 {
273 /* 273 /*
274 * Send WM_CLOSE to every admissible window. 274 * Send WM_CLOSE to every admissible window.
275 */ 275 */
276 send_message m( WM_CLOSE, 0, 0 ) ; 276 SendMessageAction m( WM_CLOSE, 0, 0 ) ;
277 iterate_our_windows( m ) ; 277 IterateOurWindows( m ) ;
278 } 278 }
279 break ; 279 break ;
280 280
281 case 4: 281 case 4:
282 /* 282 /*
283 * Oh well. Take cover. It gets violent here. Try to kill all matching proc esses. 283 * Oh well. Take cover. It gets violent here. Try to kill all matching proc esses.
284 */ 284 */
285 for (auto it = pid_set.begin(); it != pid_set.end(); ++it) 285 for (auto it = pidSet.begin(); it != pidSet.end(); ++it)
286 { 286 {
287 HANDLE tmpHandle = OpenProcess(PROCESS_TERMINATE, FALSE, *it); 287 HANDLE tmpHandle = OpenProcess(PROCESS_TERMINATE, FALSE, *it);
288 if (!tmpHandle) 288 if (!tmpHandle)
289 { 289 {
290 std::ostringstream stream; 290 std::ostringstream stream;
291 stream << "Can't open process for termination. Error: " << GetLastErro r(); 291 stream << "Can't open process for termination. Error: " << GetLastErro r();
292 session.Log(stream.str()); 292 session.Log(stream.str());
293 continue; 293 continue;
294 } 294 }
295 Windows_Handle procHandle(tmpHandle); 295 WindowsHandle procHandle(tmpHandle);
296 if (!TerminateProcess(tmpHandle, 0)) 296 if (!TerminateProcess(tmpHandle, 0))
297 { 297 {
298 std::ostringstream stream; 298 std::ostringstream stream;
299 stream << "Can't terminate process. Error: " << GetLastError(); 299 stream << "Can't terminate process. Error: " << GetLastError();
300 session.Log(stream.str()); 300 session.Log(stream.str());
301 } 301 }
302 } 302 }
303 break; 303 break;
304 304
305 default: 305 default:
306 // We're out of ways to try to shut down. 306 // We're out of ways to try to shut down.
307 return false; 307 return false;
308 } 308 }
309 309
310 /* 310 /*
311 * Wait loop. 311 * Wait loop.
312 */ 312 */
313 for ( unsigned int j = 0 ; j < 50 ; ++ j ) 313 for ( unsigned int j = 0 ; j < 50 ; ++ j )
314 { 314 {
315 std::this_thread::sleep_for( std::chrono::milliseconds( 30 ) ) ; 315 std::this_thread::sleep_for( std::chrono::milliseconds( 30 ) ) ;
316 Refresh() ; 316 Refresh() ;
317 if ( ! IsRunning() ) 317 if ( ! IsRunning() )
318 { 318 {
319 return true ; 319 return true ;
320 } 320 }
321 } 321 }
322 // Assert is_running() 322 // Assert IsRunning()
323 } 323 }
324 // No control path leaves the for-loop. 324 // No control path leaves the for-loop.
325 } ; 325 } ;
326 326
OLDNEW
« no previous file with comments | « installer/src/installer-lib/process.h ('k') | installer/src/installer-lib/property.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld