| OLD | NEW |
| 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 | 9 |
| 10 //------------------------------------------------------- | 10 //------------------------------------------------------- |
| 11 //------------------------------------------------------- | 11 //------------------------------------------------------- |
| 12 bool process_by_any_exe_with_any_module::operator()( const PROCESSENTRY32W & pro
cess ) | 12 bool process_by_any_exe_with_any_module::operator()( const PROCESSENTRY32W & pro
cess ) |
| 13 { | 13 { |
| 14 if (processNames.find(process.szExeFile) != processNames.end()) | 14 if (processNames.find(process.szExeFile) != processNames.end()) |
| 15 { | 15 { |
| 16 if (moduleNames.empty()) | 16 if (moduleNames.empty()) |
| 17 return true; | 17 return true; |
| 18 | 18 |
| 19 ModulesSnapshot ms(process.th32ProcessID); | 19 Module_Snapshot ms(process.th32ProcessID); |
| 20 MODULEENTRY32W* me = ms.first(); | 20 const MODULEENTRY32W* me = ms.first(); |
| 21 while (me != NULL) | 21 while (me != 0) |
| 22 { | 22 { |
| 23 if (moduleNames.find(me->szModule) != moduleNames.end()) | 23 if (moduleNames.find(me->szModule) != moduleNames.end()) |
| 24 { | 24 { |
| 25 return true; | 25 return true; |
| 26 } | 26 } |
| 27 me = ms.next(); | 27 me = ms.next(); |
| 28 } | 28 } |
| 29 } | 29 } |
| 30 return false; | 30 return false; |
| 31 } | 31 } |
| 32 | 32 |
| 33 //------------------------------------------------------- | 33 //------------------------------------------------------- |
| 34 // creator_process | 34 // creator_process |
| 35 //------------------------------------------------------- | 35 //------------------------------------------------------- |
| 36 DWORD creator_process( HWND window ) | 36 DWORD creator_process( HWND window ) |
| 37 { | 37 { |
| 38 DWORD pid ; | 38 DWORD pid ; |
| 39 DWORD r = GetWindowThreadProcessId( window, & pid ) ; | 39 DWORD r = GetWindowThreadProcessId( window, & pid ) ; |
| 40 if ( r == 0 ) | 40 if ( r == 0 ) |
| 41 { | 41 { |
| 42 // Assert GetWindowThreadProcessId returned an error | 42 // Assert GetWindowThreadProcessId returned an error |
| 43 // If the window handle is invalid, we end up here. | 43 // If the window handle is invalid, we end up here. |
| 44 throw windows_api_error( "GetWindowThreadProcessId", r ) ; | 44 throw windows_api_error( "GetWindowThreadProcessId", r ) ; |
| 45 } | 45 } |
| 46 return pid ; | 46 return pid ; |
| 47 } | 47 } |
| 48 | 48 |
| 49 //------------------------------------------------------- | 49 //------------------------------------------------------- |
| 50 // Snapshot | |
| 51 //------------------------------------------------------- | |
| 52 Snapshot::Snapshot() | |
| 53 : handle( ::CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ) ) | |
| 54 { | |
| 55 process.dwSize = sizeof( PROCESSENTRY32W ) ; | |
| 56 } | |
| 57 | |
| 58 PROCESSENTRY32W * Snapshot::first() | |
| 59 { | |
| 60 return ::Process32FirstW(handle, &process) ? (&process) : 0; | |
| 61 } | |
| 62 | |
| 63 PROCESSENTRY32W * Snapshot::next() | |
| 64 { | |
| 65 return ::Process32NextW(handle, &process) ? (&process) : 0; | |
| 66 } | |
| 67 | |
| 68 void Snapshot::refresh() | |
| 69 { | |
| 70 handle = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); | |
| 71 } | |
| 72 | |
| 73 //------------------------------------------------------- | |
| 74 // ModulesSnapshot | |
| 75 //------------------------------------------------------- | |
| 76 ModulesSnapshot::ModulesSnapshot(DWORD processId) | |
| 77 : handle(::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, p
rocessId)) | |
| 78 { | |
| 79 module.dwSize = sizeof(MODULEENTRY32); | |
| 80 } | |
| 81 | |
| 82 MODULEENTRY32W * ModulesSnapshot::first() | |
| 83 { | |
| 84 return ::Module32FirstW(handle, &module) ? (&module) : 0; | |
| 85 } | |
| 86 | |
| 87 MODULEENTRY32W * ModulesSnapshot::next() | |
| 88 { | |
| 89 return ::Module32NextW(handle, &module) ? (&module) : 0; | |
| 90 } | |
| 91 | |
| 92 //------------------------------------------------------- | |
| 93 // send_message, send_endsession_messages | 50 // send_message, send_endsession_messages |
| 94 //------------------------------------------------------- | 51 //------------------------------------------------------- |
| 95 /** | 52 /** |
| 96 * Default process exit wait time (per message) 5000 ms | 53 * Default process exit wait time (per message) 5000 ms |
| 97 * | 54 * |
| 98 * 5 seconds is time that the system will wait before it considers a process non
-responsive. | 55 * 5 seconds is time that the system will wait before it considers a process non
-responsive. |
| 99 */ | 56 */ |
| 100 static const unsigned int timeout = 5000 ; // milliseconds | 57 static const unsigned int timeout = 5000 ; // milliseconds |
| 101 | 58 |
| 102 /** | 59 /** |
| 103 * An function object to process the results of sending window messages in send_
message. | 60 * An function object to process the results of sending window messages in send_
message. |
| 104 * | 61 * |
| 105 * We are using send_message within a system iteration over windows. | 62 * We are using send_message within a system iteration over windows. |
| 106 * The system has its own convention for continuing/breaking the iteration. | 63 * The system has its own convention for continuing/breaking the iteration. |
| 107 * This convention is assured consistently in send_message, which also provides
default behavior. | 64 * This convention is assured consistently in send_message, which also provides
default behavior. |
| 108 * This class provides the base for any variation from the default behavior. | 65 * This class provides the base for any variation from the default behavior. |
| 109 */ | 66 */ |
| 110 struct message_accumulator | 67 struct message_accumulator |
| 111 : public std::binary_function< DWORD_PTR, BOOL, bool > | 68 : public std::binary_function< DWORD_PTR, bool, bool > |
| 112 { | 69 { |
| 113 virtual result_type operator()( first_argument_type result, second_argument_ty
pe return_value ) = 0 ; | 70 virtual result_type operator()( first_argument_type result, second_argument_ty
pe return_value ) = 0 ; |
| 114 virtual ~message_accumulator() {} ; | 71 virtual ~message_accumulator() {} ; |
| 115 } ; | 72 } ; |
| 116 | 73 |
| 117 /** | 74 /** |
| 118 * Iteration action to send a message to a window and accumulate results. | 75 * Iteration action to send a message to a window and accumulate results. |
| 119 * | 76 * |
| 120 * An error sending the message is not a failure for the function a whole. | 77 * An error sending the message is not a failure for the function a whole. |
| 121 * The goal is to close the process, and if the window is no longer present, the
n the process may have already closed. | 78 * The goal is to close the process, and if the window is no longer present, the
n the process may have already closed. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 143 send_message( UINT message, WPARAM p1, LPARAM p2 ) | 100 send_message( UINT message, WPARAM p1, LPARAM p2 ) |
| 144 : message( message ), p1( p1 ), p2( p2 ), f( 0 ) | 101 : message( message ), p1( p1 ), p2( p2 ), f( 0 ) |
| 145 {} | 102 {} |
| 146 | 103 |
| 147 /* | 104 /* |
| 148 * Enumeration function applied to each window. | 105 * Enumeration function applied to each window. |
| 149 */ | 106 */ |
| 150 bool operator()( HWND window ) | 107 bool operator()( HWND window ) |
| 151 { | 108 { |
| 152 DWORD_PTR result ; | 109 DWORD_PTR result ; |
| 153 BOOL rv = SendMessageTimeoutW( window, message, p1, p2, SMTO_BLOCK, timeout,
& result ) ; | 110 LRESULT rv = SendMessageTimeoutW( window, message, p1, p2, SMTO_BLOCK, timeo
ut, & result ) ; |
| 154 /* | 111 /* |
| 155 * If we have no message accumulator, the default behavior is to iterate eve
rything. | 112 * If we have no message accumulator, the default behavior is to iterate eve
rything. |
| 156 * If we do have one, we delegate to it the decision whether to break or to
continue. | 113 * If we do have one, we delegate to it the decision whether to break or to
continue. |
| 157 */ | 114 */ |
| 158 if ( ! f ) | 115 if ( ! f ) |
| 159 { | 116 { |
| 160 return true ; | 117 return true ; |
| 161 } | 118 } |
| 162 return ( * f )( result, rv ) ; | 119 return ( * f )( result, (rv != 0) ) ; |
| 163 } | 120 } |
| 164 } ; | 121 } ; |
| 165 | 122 |
| 166 /** | 123 /** |
| 167 * Send WM_QUERYENDSESSION and WM_ENDSESSION to a window. | 124 * Send WM_QUERYENDSESSION and WM_ENDSESSION to a window. |
| 168 * | 125 * |
| 169 * This window processor tries to shut down each application individually. | 126 * This window processor tries to shut down each application individually. |
| 170 * The alternative, gathering all the query results first and only then ending s
essions, cannot be done with a single window enumeration. | 127 * The alternative, gathering all the query results first and only then ending s
essions, cannot be done with a single window enumeration. |
| 171 */ | 128 */ |
| 172 class send_endsession_messages | 129 class send_endsession_messages |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 * As usual, errors sending messages are ignored. | 164 * As usual, errors sending messages are ignored. |
| 208 */ | 165 */ |
| 209 struct endsession_accumulator : | 166 struct endsession_accumulator : |
| 210 public message_accumulator | 167 public message_accumulator |
| 211 { | 168 { |
| 212 bool permit_end_session ; ///< Accumulator variable yields final result. | 169 bool permit_end_session ; ///< Accumulator variable yields final result. |
| 213 | 170 |
| 214 /** | 171 /** |
| 215 * Enumeration function applied to each window. | 172 * Enumeration function applied to each window. |
| 216 */ | 173 */ |
| 217 bool operator()( DWORD_PTR result, BOOL return_value ) | 174 bool operator()( DWORD_PTR result, bool return_value ) |
| 218 { | 175 { |
| 219 if ( ( ! return_value ) || result ) | 176 if ( ( ! return_value ) || result ) |
| 220 { | 177 { |
| 221 // 1. If the result is true, then the process will permit WM_ENDSESSION | 178 // 1. If the result is true, then the process will permit WM_ENDSESSION |
| 222 // 2. An error sending the message counts as "no new information" | 179 // 2. An error sending the message counts as "no new information" |
| 223 return true ; | 180 return true ; |
| 224 } | 181 } |
| 225 // The first false is the result of the calculation. | 182 // The first false is the result of the calculation. |
| 226 // The second false means to terminate enumeration early. | 183 // The second false means to terminate enumeration early. |
| 227 permit_end_session = false ; | 184 permit_end_session = false ; |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 335 if ( ! is_running() ) | 292 if ( ! is_running() ) |
| 336 { | 293 { |
| 337 return true ; | 294 return true ; |
| 338 } | 295 } |
| 339 } | 296 } |
| 340 // Assert is_running() | 297 // Assert is_running() |
| 341 } | 298 } |
| 342 // No control path leaves the for-loop. | 299 // No control path leaves the for-loop. |
| 343 } ; | 300 } ; |
| 344 | 301 |
| OLD | NEW |