OLD | NEW |
1 /** | 1 /** |
2 * \file process.h | 2 * \file process.h |
3 */ | 3 */ |
4 | 4 |
5 #ifndef PROCESS_H | 5 #ifndef PROCESS_H |
6 #define PROCESS_H | 6 #define PROCESS_H |
7 | 7 |
| 8 #include "installer-lib.h" |
8 #include "handle.h" | 9 #include "handle.h" |
9 | 10 |
10 #include <string> | 11 #include <string> |
11 #include <cctype> | 12 #include <cctype> |
12 #include <vector> | 13 #include <vector> |
13 #include <set> | 14 #include <set> |
14 #include <algorithm> | 15 #include <algorithm> |
15 #include <memory> | 16 #include <memory> |
16 | 17 |
17 #include <Windows.h> | 18 #include <Windows.h> |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 continue ; | 57 continue ; |
57 } | 58 } |
58 return ( l1 < l2 ) ? -1 : +1 ; | 59 return ( l1 < l2 ) ? -1 : +1 ; |
59 } | 60 } |
60 return 0 ; | 61 return 0 ; |
61 } | 62 } |
62 } ; | 63 } ; |
63 | 64 |
64 typedef std::basic_string< wchar_t, ci_traits< wchar_t > > wstring_ci ; | 65 typedef std::basic_string< wchar_t, ci_traits< wchar_t > > wstring_ci ; |
65 | 66 |
66 | |
67 //------------------------------------------------------- | 67 //------------------------------------------------------- |
68 // file_name_set: case-insensitive wide-string set | 68 // file_name_set: case-insensitive wide-string set |
69 //------------------------------------------------------- | 69 //------------------------------------------------------- |
70 struct file_name_set | 70 struct file_name_set |
71 : public std::set< wstring_ci > | 71 : public std::set< wstring_ci > |
72 { | 72 { |
73 /** | 73 /** |
74 * Empty set constructor. | 74 * Empty set constructor. |
75 */ | 75 */ |
76 file_name_set() | 76 file_name_set() |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 * | 160 * |
161 * \sa | 161 * \sa |
162 * MSDN [GetWindowThreadProcessId function](http://msdn.microsoft.com/en-us/li
brary/windows/desktop/ms633522%28v=vs.85%29.aspx) | 162 * MSDN [GetWindowThreadProcessId function](http://msdn.microsoft.com/en-us/li
brary/windows/desktop/ms633522%28v=vs.85%29.aspx) |
163 */ | 163 */ |
164 DWORD creator_process( HWND window ) ; | 164 DWORD creator_process( HWND window ) ; |
165 | 165 |
166 //------------------------------------------------------- | 166 //------------------------------------------------------- |
167 // Snapshot | 167 // Snapshot |
168 //------------------------------------------------------- | 168 //------------------------------------------------------- |
169 /** | 169 /** |
170 * A snapshot of all the processes running on the system. | 170 * Traits class for snapshots of all processes on the system. |
| 171 */ |
| 172 struct Process_Snapshot_Traits |
| 173 { |
| 174 /** |
| 175 * The type of the data resulting from CreateToolhelp32Snapshot. |
| 176 */ |
| 177 typedef PROCESSENTRY32W result_type ; |
| 178 |
| 179 /** |
| 180 * Flags used to call CreateToolhelp32Snapshot. |
| 181 */ |
| 182 const static DWORD snapshot_flags = TH32CS_SNAPPROCESS ; |
| 183 |
| 184 /** |
| 185 * Wrapper for 'first' function for processes |
| 186 */ |
| 187 static BOOL first( HANDLE arg1, LPPROCESSENTRY32 arg2 ) |
| 188 { |
| 189 return ::Process32First( arg1, arg2 ) ; |
| 190 } |
| 191 |
| 192 /** |
| 193 * Wrapper for 'next' function for processes |
| 194 */ |
| 195 static BOOL next( HANDLE arg1, LPPROCESSENTRY32 arg2 ) |
| 196 { |
| 197 return ::Process32Next( arg1, arg2 ) ; |
| 198 } |
| 199 } ; |
| 200 |
| 201 /** |
| 202 * Traits class for snapshots of all modules loaded by a process. |
| 203 */ |
| 204 struct Module_Snapshot_Traits |
| 205 { |
| 206 /** |
| 207 * The type of the data resulting from CreateToolhelp32Snapshot. |
| 208 */ |
| 209 typedef MODULEENTRY32W result_type ; |
| 210 |
| 211 /** |
| 212 * Flags used to call CreateToolhelp32Snapshot. |
| 213 */ |
| 214 const static DWORD snapshot_flags = TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32 ; |
| 215 |
| 216 /** |
| 217 * Wrapper for 'first' function for modules |
| 218 */ |
| 219 static BOOL first( HANDLE arg1, LPMODULEENTRY32 arg2 ) |
| 220 { |
| 221 return ::Module32First( arg1, arg2 ) ; |
| 222 } |
| 223 |
| 224 /** |
| 225 * Wrapper for 'next' function for modules |
| 226 */ |
| 227 static BOOL next( HANDLE arg1, LPMODULEENTRY32 arg2 ) |
| 228 { |
| 229 return ::Module32Next( arg1, arg2 ) ; |
| 230 } |
| 231 } ; |
| 232 |
| 233 /** |
| 234 * A snapshot wrapping the results of CreateToolhelp32Snapshot system call. |
171 * | 235 * |
172 * Unfortunately, we cannot provide standard iterator for this class. | 236 * Unfortunately, we cannot provide standard iterator for this class. |
173 * Standard iterators must be copy-constructible, which entails the possibility
of multiple, coexisting iteration states. | 237 * Standard iterators must be copy-constructible, which entails the possibility
of multiple, coexisting iteration states. |
174 * The iteration behavior provided by Process32First and Process32Next relies up
on state held within the snapshot itself. | 238 * The iteration behavior provided by Process32First and Process32Next relies up
on state held within the snapshot itself. |
175 * Thus, there can be only one iterator at a time for the snapshot. | 239 * Thus, there can be only one iterator at a time for the snapshot. |
176 * The two requirements are not simultaneously satisfiable. | 240 * The two requirements are not simultaneously satisfiable. |
177 * | 241 * |
178 * As a substitute for a standard iterator, we provide a few functions mimicking
the pattern of standard iterators. | 242 * Instead of a standard iterator, we provide a first() and next() functions wra
pping the corresponding system calls. |
179 * This class acts as its own iterator. | |
180 * The pointer returned is either one to the member variable "process" or else 0
. | |
181 * | 243 * |
182 * \par Implementation | 244 * \par Implementation |
183 * | 245 * |
184 * - MSDN [CreateToolhelp32Snapshot function](http://msdn.microsoft.com/en-us/li
brary/windows/desktop/ms682489%28v=vs.85%29.aspx) | 246 * - MSDN [CreateToolhelp32Snapshot function](http://msdn.microsoft.com/en-us/li
brary/windows/desktop/ms682489%28v=vs.85%29.aspx) |
185 * - MSDN [Process32First function](http://msdn.microsoft.com/en-us/library/wind
ows/desktop/ms684834%28v=vs.85%29.aspx) | 247 * - MSDN [Process32First function](http://msdn.microsoft.com/en-us/library/wind
ows/desktop/ms684834%28v=vs.85%29.aspx) |
186 * - MSDN [Process32Next function](http://msdn.microsoft.com/en-us/library/windo
ws/desktop/ms684836%28v=vs.85%29.aspx) | 248 * - MSDN [Process32Next function](http://msdn.microsoft.com/en-us/library/windo
ws/desktop/ms684836%28v=vs.85%29.aspx) |
187 * - MSDN [PROCESSENTRY32 structure](http://msdn.microsoft.com/en-us/library/win
dows/desktop/ms684839%28v=vs.85%29.aspx) | 249 * - MSDN [PROCESSENTRY32 structure](http://msdn.microsoft.com/en-us/library/win
dows/desktop/ms684839%28v=vs.85%29.aspx) |
| 250 * |
| 251 * \par Design Note |
| 252 * The traits class defines first() and next() functions instead of using func
tion pointers. |
| 253 * This arises from a limitation in the compiler. |
| 254 * The system calls are declared 'WINAPI', which is a compiler-specific extens
ion. |
| 255 * That extension, however, does not go far enough to be able to declare a poi
nter with the same modifier. |
| 256 * Hence the system calls must be called directly; they are wrapped in the tra
it functions. |
188 */ | 257 */ |
| 258 template< class Traits > |
189 class Snapshot | 259 class Snapshot |
190 { | 260 { |
| 261 public: |
191 /** | 262 /** |
192 * Handle to the process snapshot. | 263 * Expose the result type from the traits class as our own. |
| 264 */ |
| 265 typedef typename Traits::result_type result_type ; |
| 266 |
| 267 private: |
| 268 /** |
| 269 * Process ID argument for CreateToolhelp32Snapshot. |
| 270 */ |
| 271 DWORD _id ; |
| 272 |
| 273 /** |
| 274 * Handle to the underlying snapshot. |
193 */ | 275 */ |
194 Windows_Handle handle ; | 276 Windows_Handle handle ; |
195 | 277 |
196 /** | 278 /** |
197 * Buffer for reading a single process entry out of the snapshot. | 279 * Buffer for reading a single process entry out of the snapshot. |
| 280 * |
| 281 * This buffer is constant insofar as the code outside this class is concerned
. |
| 282 * The accessor functions first() and next() return pointers to constant resul
t_type. |
198 */ | 283 */ |
199 PROCESSENTRY32W process; | 284 result_type buffer; |
200 | 285 |
201 /** | 286 /** |
202 * Copy constructor declared private and not defined. | 287 * Copy constructor declared private and not defined. |
203 * | 288 * |
204 * \par Implementation | 289 * \par Implementation |
205 * Add "= delete" for C++11. | 290 * Add "= delete" for C++11. |
206 */ | 291 */ |
207 Snapshot( const Snapshot & ) ; | 292 Snapshot( const Snapshot & ) ; |
208 | 293 |
209 /** | 294 /** |
210 * Copy assignment declared private and not defined. | 295 * Copy assignment declared private and not defined. |
211 * | 296 * |
212 * \par Implementation | 297 * \par Implementation |
213 * Add "= delete" for C++11. | 298 * Add "= delete" for C++11. |
214 */ | 299 */ |
215 Snapshot operator=( const Snapshot & ) ; | 300 Snapshot operator=( const Snapshot & ) ; |
216 | 301 |
| 302 /** |
| 303 * Create a new snapshot and return its handle. |
| 304 */ |
| 305 Windows_Handle::handle_type make_handle() |
| 306 { |
| 307 Windows_Handle::handle_type h = ::CreateToolhelp32Snapshot( Traits::snapshot
_flags, _id ) ; |
| 308 if ( h == INVALID_HANDLE_VALUE ) |
| 309 { |
| 310 throw windows_api_error( "CreateToolhelp32Snapshot", "INVALID_HANDLE_VALUE
" ) ; |
| 311 } |
| 312 return h ; |
| 313 } |
| 314 |
| 315 protected: |
| 316 /** |
| 317 * Constructor takes a snapshot. |
| 318 */ |
| 319 Snapshot( DWORD id ) |
| 320 : _id( id ), handle( make_handle() ) |
| 321 { |
| 322 // The various result types all define 'dwSize' with the same semantics. |
| 323 buffer.dwSize = sizeof( result_type ) ; |
| 324 } |
217 | 325 |
218 public: | 326 public: |
219 /** | 327 /** |
220 * Default constructor takes the snapshot. | 328 * Reconstruct the current instance with a new system snapshot. |
| 329 * |
| 330 * This function uses reinitialization assignment in the Windows_Handle class, |
| 331 * which takes care of closing the old handle. |
221 */ | 332 */ |
222 Snapshot() ; | 333 void refresh() |
| 334 { |
| 335 handle = make_handle(); |
| 336 } |
223 | 337 |
224 /** | 338 /** |
225 * Reconstruct the current instance with a new system snapshot. | 339 * Retrieve the first snapshot item into our member buffer. |
| 340 * |
| 341 * \return |
| 342 * Pointer to our member buffer if there was a first item |
| 343 * 0 otherwise |
| 344 * |
| 345 * \par Design Note |
| 346 * There's no error handling in the present version of this function. |
| 347 * In part that's because the underlying system call returns either true or
false, both of which are ordinarily valid answers. |
| 348 * The trouble is that a false return is overloaded. |
| 349 * It can mean either that (ordinary) there are no more items or (exceptiona
l) the snapshot did not contain the right kind of item. |
| 350 * GetLastError is no help here; it doesn't distinguish between these cases. |
| 351 * The upshot is that we rely that our implementation calls the right functi
ons on the snapshot, |
| 352 * and so we ignore the case where we've passed bad arguments to the syste
m call. |
226 */ | 353 */ |
227 void refresh() ; | 354 const result_type * first() |
| 355 { |
| 356 return Traits::first(handle, &buffer) ? &buffer : 0; |
| 357 } |
228 | 358 |
229 /** | 359 /** |
230 * Return a pointer to the first process in the snapshot. | 360 * Retrieve the next snapshot item into our member buffer and return a pointer
to it. |
| 361 * begin() must have been called first. |
| 362 * |
| 363 * \return |
| 364 * Pointer to our member buffer if there was a first item |
| 365 * 0 otherwise |
| 366 * |
| 367 * \par Design Note |
| 368 * See the Design Note for first(); the same considerations apply here. |
231 */ | 369 */ |
232 PROCESSENTRY32W * first() ; | 370 const result_type * next() |
233 | 371 { |
234 /** | 372 return Traits::next(handle, &buffer) ? &buffer : 0; |
235 * Return a pointer to the next process in the snapshot. | 373 } |
236 * begin() must have been called first. | |
237 */ | |
238 PROCESSENTRY32W * next() ; | |
239 } ; | 374 } ; |
240 | 375 |
241 class ModulesSnapshot | 376 /** |
| 377 * A snapshot of all processes running on the system. |
| 378 */ |
| 379 struct Process_Snapshot |
| 380 : public Snapshot< Process_Snapshot_Traits > |
242 { | 381 { |
243 /** | 382 Process_Snapshot() |
244 * Handle to the process snapshot. | 383 : Snapshot( 0 ) |
245 */ | 384 {} |
246 Windows_Handle handle; | 385 } ; |
247 | 386 |
248 /** | 387 /** |
249 * Buffer for reading a single module entry out of the snapshot. | 388 * A snapshot of all modules loaded for a given process. |
250 */ | 389 */ |
251 MODULEENTRY32W module; | 390 struct Module_Snapshot |
252 | 391 : public Snapshot< Module_Snapshot_Traits > |
253 /** | 392 { |
254 * Copy constructor declared private and not defined. | 393 Module_Snapshot( DWORD process_id ) |
255 * | 394 : Snapshot( process_id ) |
256 * \par Implementation | 395 {} |
257 * Add "= delete" for C++11. | 396 } ; |
258 */ | |
259 ModulesSnapshot(const ModulesSnapshot&); | |
260 | |
261 /** | |
262 * Copy assignment declared private and not defined. | |
263 * | |
264 * \par Implementation | |
265 * Add "= delete" for C++11. | |
266 */ | |
267 ModulesSnapshot operator=(const ModulesSnapshot&); | |
268 | |
269 | |
270 public: | |
271 /** | |
272 * Default constructor takes the snapshot. | |
273 */ | |
274 ModulesSnapshot(DWORD processId); | |
275 | |
276 /** | |
277 * Return a pointer to the first process in the snapshot. | |
278 */ | |
279 MODULEENTRY32W* first(); | |
280 | |
281 /** | |
282 * Return a pointer to the next process in the snapshot. | |
283 * begin() must have been called first. | |
284 */ | |
285 MODULEENTRY32W* next(); | |
286 }; | |
287 | |
288 | 397 |
289 //------------------------------------------------------- | 398 //------------------------------------------------------- |
290 // initialize_process_list | 399 // initialize_process_list |
291 //------------------------------------------------------- | 400 //------------------------------------------------------- |
292 /** | 401 /** |
293 * \tparam T The type into which a PROCESSENTRY32W struture is extracted. | 402 * \tparam T The type into which a PROCESSENTRY32W struture is extracted. |
294 * \tparam Admittance Function type for argument 'admit' | 403 * \tparam Admittance Function type for argument 'admit' |
295 * \tparam Extractor Function type for argument 'extract' | 404 * \tparam Extractor Function type for argument 'extract' |
296 * \param admit A unary predicate function class that determines what's included | 405 * \param admit A unary predicate function class that determines what's included |
297 * A process appears in the list only if the predicate returns true. | 406 * A process appears in the list only if the predicate returns true. |
298 * The use of this predicate is analogous to that in std::copy_if. | 407 * The use of this predicate is analogous to that in std::copy_if. |
299 * \param convert A conversion function that takes a PROCESSENTRY32W as input ar
gument and returns an element of type T. | 408 * \param convert A conversion function that takes a PROCESSENTRY32W as input ar
gument and returns an element of type T. |
300 */ | 409 */ |
301 template<class T, class Admittance, class Extractor> | 410 template<class T, class Admittance, class Extractor> |
302 void initialize_process_list(std::vector<T>& v, Snapshot& snap, Admittance admit
= Admittance(), Extractor extract = Extractor()) | 411 void initialize_process_list(std::vector<T>& v, Process_Snapshot &snap, Admittan
ce admit = Admittance(), Extractor extract = Extractor()) |
303 { | 412 { |
304 PROCESSENTRY32W* p = snap.first(); | 413 const PROCESSENTRY32W* p = snap.first(); |
305 while (p != NULL) | 414 while (p != 0) |
306 { | 415 { |
307 if (admit(*p )) | 416 if (admit(*p )) |
308 { | 417 { |
309 /* | 418 /* |
310 * We don't have C++11 emplace_back, which can construct the element in p
lace. | 419 * We don't have C++11 emplace_back, which can construct the element in p
lace. |
311 * Instead, we copy the return value of the converter. | 420 * Instead, we copy the return value of the converter. |
312 */ | 421 */ |
313 v.push_back(extract(*p)); | 422 v.push_back(extract(*p)); |
314 } | 423 } |
315 p = snap.next(); | 424 p = snap.next(); |
316 } | 425 } |
317 }; | 426 }; |
318 | 427 |
319 //------------------------------------------------------- | 428 //------------------------------------------------------- |
320 // initialize_process_set | 429 // initialize_process_set |
321 //------------------------------------------------------- | 430 //------------------------------------------------------- |
322 /** | 431 /** |
323 * \tparam T The type into which a PROCESSENTRY32W struture is extracted. | 432 * \tparam T The type into which a PROCESSENTRY32W struture is extracted. |
324 * \tparam Admittance Function type for argument 'admit' | 433 * \tparam Admittance Function type for argument 'admit' |
325 * \tparam Extractor Function type for argument 'extract' | 434 * \tparam Extractor Function type for argument 'extract' |
326 * \param admit A unary predicate function class that determines what's included | 435 * \param admit A unary predicate function class that determines what's included |
327 * A process appears in the list only if the predicate returns true. | 436 * A process appears in the list only if the predicate returns true. |
328 * The use of this predicate is analogous to that in std::copy_if. | 437 * The use of this predicate is analogous to that in std::copy_if. |
329 * \param convert A conversion function that takes a PROCESSENTRY32W as input ar
gument and returns an element of type T. | 438 * \param convert A conversion function that takes a PROCESSENTRY32W as input ar
gument and returns an element of type T. |
330 */ | 439 */ |
331 template<class T, class Admittance, class Extractor> | 440 template<class T, class Admittance, class Extractor> |
332 void initialize_process_set(std::set< T > & set, Snapshot& snap, Admittance admi
t = Admittance(), Extractor extract = Extractor()) | 441 void initialize_process_set(std::set< T > & set, Process_Snapshot &snap, Admitta
nce admit = Admittance(), Extractor extract = Extractor()) |
333 { | 442 { |
334 PROCESSENTRY32W* p = snap.first(); | 443 const PROCESSENTRY32W* p = snap.first(); |
335 while (p != NULL) | 444 while (p != 0) |
336 { | 445 { |
337 if (admit(*p)) | 446 if (admit(*p)) |
338 { | 447 { |
339 set.insert(extract(*p)); | 448 set.insert(extract(*p)); |
340 } | 449 } |
341 p = snap.next(); | 450 p = snap.next(); |
342 } | 451 } |
343 }; | 452 }; |
344 | 453 |
345 //------------------------------------------------------- | 454 //------------------------------------------------------- |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
507 process_by_any_exe_with_any_module filter ; | 616 process_by_any_exe_with_any_module filter ; |
508 | 617 |
509 /** | 618 /** |
510 * Copy function object copies just the process ID. | 619 * Copy function object copies just the process ID. |
511 */ | 620 */ |
512 copy_PID copy ; | 621 copy_PID copy ; |
513 | 622 |
514 /** | 623 /** |
515 * Snapshot of running processes. | 624 * Snapshot of running processes. |
516 */ | 625 */ |
517 Snapshot & snapshot ; | 626 Process_Snapshot & snapshot ; |
518 | 627 |
519 void update() | 628 void update() |
520 { | 629 { |
521 initialize_process_set( pid_set, snapshot, filter, copy ) ; | 630 initialize_process_set( pid_set, snapshot, filter, copy ) ; |
522 } ; | 631 } ; |
523 | 632 |
524 template< class F > | 633 template< class F > |
525 class only_our_processes | 634 class only_our_processes |
526 { | 635 { |
527 Process_Closer & self ; | 636 Process_Closer & self ; |
(...skipping 21 matching lines...) Expand all Loading... |
549 { | 658 { |
550 // Assert the process that created the window is not in our pid_set | 659 // Assert the process that created the window is not in our pid_set |
551 return true ; | 660 return true ; |
552 } | 661 } |
553 return f( window ) ; | 662 return f( window ) ; |
554 } | 663 } |
555 } ; | 664 } ; |
556 | 665 |
557 public: | 666 public: |
558 template <size_t n_file_names, size_t n_module_names> | 667 template <size_t n_file_names, size_t n_module_names> |
559 Process_Closer(Snapshot & snapshot, const wchar_t* (&file_name_list)[n_file_na
mes], const wchar_t* (&module_name_list)[n_module_names]) | 668 Process_Closer(Process_Snapshot & snapshot, const wchar_t* (&file_name_list)[n
_file_names], const wchar_t* (&module_name_list)[n_module_names]) |
560 : snapshot(snapshot), process_names(file_name_list), module_names(module_nam
e_list), filter(process_names, module_names) | 669 : snapshot(snapshot), process_names(file_name_list), module_names(module_nam
e_list), filter(process_names, module_names) |
561 { | 670 { |
562 update() ; | 671 update() ; |
563 } | 672 } |
564 template <size_t n_file_names> | 673 template <size_t n_file_names> |
565 Process_Closer(Snapshot & snapshot, const wchar_t * (&file_name_list)[n_file_n
ames]) | 674 Process_Closer(Process_Snapshot & snapshot, const wchar_t * (&file_name_list)[
n_file_names]) |
566 : snapshot(snapshot), process_names(file_name_list), module_names(), filter(
process_names, module_names) | 675 : snapshot(snapshot), process_names(file_name_list), module_names(), filter(
process_names, module_names) |
567 { | 676 { |
568 update() ; | 677 update() ; |
569 } | 678 } |
570 | 679 |
571 /** | 680 /** |
572 * Refresh our state to match the snapshot state. | 681 * Refresh our state to match the snapshot state. |
573 */ | 682 */ |
574 void refresh() | 683 void refresh() |
575 { | 684 { |
(...skipping 13 matching lines...) Expand all Loading... |
589 } | 698 } |
590 | 699 |
591 /* | 700 /* |
592 * Shut down every process in the pid_set. | 701 * Shut down every process in the pid_set. |
593 */ | 702 */ |
594 bool shut_down() ; | 703 bool shut_down() ; |
595 | 704 |
596 } ; | 705 } ; |
597 | 706 |
598 #endif | 707 #endif |
OLD | NEW |