| Left: | ||
| Right: |
| 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 "handle.h" | 8 #include "handle.h" |
| 9 | 9 |
| 10 #include <string> | |
| 11 #include <cctype> | |
| 10 #include <vector> | 12 #include <vector> |
| 11 #include <set> | 13 #include <set> |
| 12 #include <algorithm> | 14 #include <algorithm> |
| 13 #include <memory> | 15 #include <memory> |
| 14 | 16 |
| 15 #include <Windows.h> | 17 #include <Windows.h> |
| 16 #include <TlHelp32.h> | 18 #include <TlHelp32.h> |
| 17 | 19 |
| 20 //------------------------------------------------------- | |
| 21 // wstring_ci: case-insensitive wide string | |
| 22 //------------------------------------------------------- | |
| 18 | 23 |
| 19 //------------------------------------------------------- | 24 /** |
| 20 // exe_name_set: case-insensitive wide-string set | 25 * Traits class for case-insensitive strings. |
| 21 //------------------------------------------------------- | 26 */ |
| 22 int wcscmpi( const wchar_t * s1, const wchar_t * s2 ) ; | 27 template< class T > |
|
Wladimir Palant
2014/03/31 05:58:35
Style nit: excessive whitespace. There should be n
| |
| 28 struct ci_traits: std::char_traits< T > | |
| 29 { | |
| 30 static bool eq( T c1, T c2 ) | |
| 31 { | |
| 32 return std::tolower( c1 ) == std::tolower( c2 ) ; | |
| 33 } | |
| 23 | 34 |
| 24 struct exe_name | 35 static bool lt( T c1, T c2 ) |
| 25 { | 36 { |
| 37 return std::tolower( c1 ) < std::tolower( c2 ) ; | |
| 38 } | |
| 39 | |
| 26 /** | 40 /** |
| 27 * Pointer to wide-character string, which is supposed to be null-terminated. | 41 * Trait comparison function. |
| 42 * | |
| 43 * Note that this is not a comparison of C-style strings. | |
| 44 * In particular, there's no concern over null characters '\0'. | |
| 45 * The argument 'n' is the minimum length of the two strings being compared. | |
| 46 * We may assume that the intervals p1[0..n) and p2[0..n) are both valid subst rings. | |
| 28 */ | 47 */ |
| 29 const wchar_t * name ; | 48 static int compare( const T * p1, const T * p2, size_t n ) |
|
Oleksandr
2014/03/31 07:03:03
Once again, I think it would be much easier to jus
Wladimir Palant
2014/03/31 09:33:34
That's the standard way of doing this actually. Wh
Eric
2014/03/31 14:13:54
It would work, obviously, since that's what we wer
| |
| 30 | |
| 31 exe_name( const wchar_t * name ) : name( name ) {} ; | |
| 32 } ; | |
| 33 | |
| 34 template <> | |
| 35 struct std::less< exe_name > | |
| 36 : std::binary_function< exe_name, exe_name, bool > | |
| 37 { | |
| 38 bool operator()( const exe_name & a, const exe_name & b ) const | |
| 39 { | 49 { |
| 40 return wcscmpi( a.name, b.name ) < 0 ; | 50 while ( n-- > 0 ) |
|
Wladimir Palant
2014/03/31 05:58:35
Style nit: excessive whitespace. There should be n
| |
| 51 { | |
| 52 T l1 = std::tolower( * p1 ++ ) ; | |
| 53 T l2 = std::tolower( * p2 ++ ) ; | |
|
Wladimir Palant
2014/03/31 05:58:35
Style nit: excessive whitespace. There should be n
| |
| 54 if ( l1 == l2 ) | |
| 55 { | |
| 56 » continue ; | |
|
Wladimir Palant
2014/03/31 09:33:34
Didn't notice it originally - please use spaces fo
Eric
2014/03/31 14:13:54
That's Visual Studio acting up again. I thought I
| |
| 57 } | |
| 58 return ( l1 < l2 ) ? -1 : +1 ; | |
| 59 } | |
| 60 return 0 ; | |
| 41 } | 61 } |
| 42 } ; | 62 } ; |
| 43 | 63 |
| 44 struct exe_name_set | 64 typedef std::basic_string< wchar_t, ci_traits< wchar_t > > wstring_ci ; |
| 45 : public std::set< exe_name > | 65 |
| 66 | |
| 67 //------------------------------------------------------- | |
| 68 // file_name_set: case-insensitive wide-string set | |
| 69 //------------------------------------------------------- | |
| 70 struct file_name_set | |
| 71 : public std::set< wstring_ci > | |
| 46 { | 72 { |
| 47 exe_name_set( const wchar_t * exe_name_list[], size_t n_exe_names ) | 73 /** |
| 74 * Constructor initialization from an array. | |
| 75 */ | |
| 76 template< size_t n_file_names > | |
| 77 file_name_set( const wchar_t * ( & file_name_list )[ n_file_names ] ) | |
|
Wladimir Palant
2014/03/31 05:58:35
Style nit: excessive whitespace. There should be n
Wladimir Palant
2014/03/31 05:58:35
We might want to have a non-templated version of t
Eric
2014/03/31 14:13:54
We're also getting an empty-set constructor for th
| |
| 48 { | 78 { |
| 49 for ( unsigned int j = 0 ; j < n_exe_names ; ++ j ) | 79 for ( unsigned int j = 0 ; j < n_file_names ; ++ j ) |
| 50 { | 80 { |
| 51 insert( exe_name( exe_name_list[ j ] ) ) ; | 81 insert( wstring_ci( file_name_list[ j ] ) ) ; |
| 52 } | 82 } |
| 53 } | 83 } |
| 84 | |
| 85 /** | |
| 86 * Empty set constructor has no arguments. | |
| 87 */ | |
| 88 file_name_set() | |
| 89 {} | |
|
Wladimir Palant
2014/03/31 05:58:35
Style nit: closing bracket should go on a new line
| |
| 54 } ; | 90 } ; |
| 55 | 91 |
| 56 //------------------------------------------------------- | 92 //------------------------------------------------------- |
| 57 //------------------------------------------------------- | 93 //------------------------------------------------------- |
| 58 /** | 94 /** |
| 59 * Filter by process name. Comparison is case-insensitive. | 95 * Filter by process name. Comparison is case-insensitive. |
| 60 */ | 96 */ |
| 61 class process_by_any_exe_name_CI | 97 class process_by_any_exe_name_CI |
| 62 : public std::unary_function< PROCESSENTRY32W, bool > | 98 : public std::unary_function< PROCESSENTRY32W, bool > |
| 63 { | 99 { |
| 64 const exe_name_set & names ; | 100 const file_name_set & names ; |
|
Wladimir Palant
2014/03/31 05:58:35
Please don't use references as class members, crea
Eric
2014/03/31 14:13:54
In this case, we can. This class is entirely subor
| |
| 65 public: | 101 public: |
| 66 bool operator()( const PROCESSENTRY32W & ) ; | 102 bool operator()( const PROCESSENTRY32W & process ) |
| 67 process_by_any_exe_name_CI( const exe_name_set & names ) | 103 { |
| 104 return names.find( process.szExeFile ) != names.end() ; | |
| 105 } | |
|
Wladimir Palant
2014/03/31 05:58:35
Nothing wrong with keeping implementations out of
Eric
2014/03/31 14:13:54
No, there's not. There's nothing wrong with puttin
| |
| 106 | |
| 107 process_by_any_exe_name_CI( const file_name_set & names ) | |
| 68 : names( names ) | 108 : names( names ) |
| 69 {} | 109 {} |
| 70 } ; | 110 } ; |
| 71 | 111 |
| 72 //------------------------------------------------------- | 112 //------------------------------------------------------- |
| 73 // Process utility functions. | 113 // Process utility functions. |
| 74 //------------------------------------------------------- | 114 //------------------------------------------------------- |
| 75 /** | 115 /** |
| 76 * A promiscuous filter admits everything. | 116 * A promiscuous filter admits everything. |
| 77 */ | 117 */ |
| 78 struct every_process | 118 struct every_process |
| 79 : public std::unary_function< PROCESSENTRY32W, bool > | 119 : public std::unary_function< PROCESSENTRY32W, bool > |
| 80 { | 120 { |
| 81 bool operator()( const PROCESSENTRY32W & ) { return true ; } ; | 121 bool operator()( const PROCESSENTRY32W & ) { return true ; } ; |
| 82 } ; | 122 } ; |
| 83 | 123 |
| 84 /** | 124 /** |
| 85 * Filter by process name. Comparison is case-insensitive. | |
| 86 */ | |
| 87 class process_by_name_CI | |
| 88 : public std::unary_function< PROCESSENTRY32W, bool > | |
| 89 { | |
| 90 const wchar_t * name ; | |
| 91 const size_t length ; | |
| 92 process_by_name_CI() ; | |
| 93 public: | |
| 94 bool operator()( const PROCESSENTRY32W & ) ; | |
| 95 process_by_name_CI( const wchar_t * name ) ; | |
| 96 } ; | |
| 97 | |
| 98 /** | |
| 99 * Extractor that copies the entire process structure. | 125 * Extractor that copies the entire process structure. |
| 100 */ | 126 */ |
| 101 struct copy_all | 127 struct copy_all |
| 102 : public std::unary_function< PROCESSENTRY32W, PROCESSENTRY32W > | 128 : public std::unary_function< PROCESSENTRY32W, PROCESSENTRY32W > |
| 103 { | 129 { |
| 104 PROCESSENTRY32W operator()( const PROCESSENTRY32W & process ) { return process ; } | 130 PROCESSENTRY32W operator()( const PROCESSENTRY32W & process ) { return process ; } |
| 105 } ; | 131 } ; |
| 106 | 132 |
| 107 /** | 133 /** |
| 108 * Extractor that copies only the PID. | 134 * Extractor that copies only the PID. |
| 109 */ | 135 */ |
| 110 struct copy_PID | 136 struct copy_PID |
| 111 : public std::unary_function< PROCESSENTRY32W, DWORD > | 137 : public std::unary_function< PROCESSENTRY32W, DWORD > |
| 112 { | 138 { |
| 113 inline DWORD operator()( const PROCESSENTRY32W & process ) { return process.th 32ProcessID ; } | 139 inline DWORD operator()( const PROCESSENTRY32W & process ) { return process.th 32ProcessID ; } |
| 114 } ; | 140 } ; |
| 115 | 141 |
| 116 /** | 142 /** |
| 117 * Case-insensitive wide-character C-style string comparison, fixed-length | |
| 118 */ | |
| 119 int wcsncmpi( const wchar_t * a, const wchar_t * b, unsigned int length ) ; | |
| 120 | |
| 121 /** | |
| 122 * Retrieve the process ID that created a window. | 143 * Retrieve the process ID that created a window. |
| 123 * | 144 * |
| 124 * Wrapper around GetWindowThreadProcessId. | 145 * Wrapper around GetWindowThreadProcessId. |
| 125 * Converts an error return from the system call into an exception. | 146 * Converts an error return from the system call into an exception. |
| 126 * The system call can also retrieve the creating thread; we ignore it. | 147 * The system call can also retrieve the creating thread; we ignore it. |
| 127 * | 148 * |
| 128 * \param window | 149 * \param window |
| 129 * Handle of the window | 150 * Handle of the window |
| 130 * \return | 151 * \return |
| 131 * ID of the process that created the argument window | 152 * ID of the process that created the argument window |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 424 * Set of process identifiers matching one of the executable names. | 445 * Set of process identifiers matching one of the executable names. |
| 425 */ | 446 */ |
| 426 std::set< DWORD > pid_set ; | 447 std::set< DWORD > pid_set ; |
| 427 | 448 |
| 428 /** | 449 /** |
| 429 * Set of executable names by which to filter. | 450 * Set of executable names by which to filter. |
| 430 * | 451 * |
| 431 * The argument of the filter constructor is a set by reference. | 452 * The argument of the filter constructor is a set by reference. |
| 432 * Since it does not make a copy for itself, we define it as a class member to provide its allocation. | 453 * Since it does not make a copy for itself, we define it as a class member to provide its allocation. |
| 433 */ | 454 */ |
| 434 exe_name_set exe_names ; | 455 file_name_set process_names ; |
| 435 | 456 |
| 436 /** | 457 /** |
| 437 * Filter function object matches on any of the exe names specified in the con structor. | 458 * Filter function object matches on any of the exe names specified in the con structor. |
| 438 */ | 459 */ |
| 439 process_by_any_exe_name_CI filter ; | 460 process_by_any_exe_name_CI filter ; |
| 440 | 461 |
| 441 /** | 462 /** |
| 442 * Copy function object copies just the process ID. | 463 * Copy function object copies just the process ID. |
| 443 */ | 464 */ |
| 444 copy_PID copy ; | 465 copy_PID copy ; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 480 if ( ! b ) | 501 if ( ! b ) |
| 481 { | 502 { |
| 482 // Assert the process that created the window is not in our pid_set | 503 // Assert the process that created the window is not in our pid_set |
| 483 return true ; | 504 return true ; |
| 484 } | 505 } |
| 485 return f( window ) ; | 506 return f( window ) ; |
| 486 } | 507 } |
| 487 } ; | 508 } ; |
| 488 | 509 |
| 489 public: | 510 public: |
| 490 Process_Closer( Snapshot & snapshot, const wchar_t * exe_name_list[], size_t n _exe_names ) | 511 template< size_t n_process_names > |
| 491 : snapshot( snapshot ), exe_names( exe_name_list, n_exe_names ), filter( exe _names ) | 512 Process_Closer( Snapshot & snapshot, const wchar_t * ( & process_name_list )[ n_process_names ] ) |
| 513 : snapshot( snapshot ), process_names( process_name_list ), filter( process_ names ) | |
| 492 { | 514 { |
| 493 update() ; | 515 update() ; |
| 494 } | 516 } |
| 495 | 517 |
| 496 /** | 518 /** |
| 497 * Refresh our state to match the snapshot state. | 519 * Refresh our state to match the snapshot state. |
| 498 */ | 520 */ |
| 499 void refresh() | 521 void refresh() |
| 500 { | 522 { |
| 501 pid_set.clear() ; | 523 pid_set.clear() ; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 514 } | 536 } |
| 515 | 537 |
| 516 /* | 538 /* |
| 517 * Shut down every process in the pid_set. | 539 * Shut down every process in the pid_set. |
| 518 */ | 540 */ |
| 519 bool shut_down() ; | 541 bool shut_down() ; |
| 520 | 542 |
| 521 } ; | 543 } ; |
| 522 | 544 |
| 523 #endif | 545 #endif |
| OLD | NEW |