OLD | NEW |
(Empty) | |
| 1 /** |
| 2 * \file process.h |
| 3 */ |
| 4 |
| 5 #ifndef PROCESS_H |
| 6 #define PROCESS_H |
| 7 |
| 8 #include "installer-lib.h" |
| 9 #include "handle.h" |
| 10 |
| 11 #include <string> |
| 12 #include <cctype> |
| 13 #include <vector> |
| 14 #include <set> |
| 15 #include <algorithm> |
| 16 #include <memory> |
| 17 |
| 18 #include <Windows.h> |
| 19 #include <TlHelp32.h> |
| 20 |
| 21 //------------------------------------------------------- |
| 22 // wstring_ci: case-insensitive wide string |
| 23 //------------------------------------------------------- |
| 24 |
| 25 /** |
| 26 * Traits class for case-insensitive strings. |
| 27 */ |
| 28 template< class T > |
| 29 struct ci_traits: std::char_traits< T > |
| 30 { |
| 31 static bool eq( T c1, T c2 ) |
| 32 { |
| 33 return std::tolower( c1 ) == std::tolower( c2 ) ; |
| 34 } |
| 35 |
| 36 static bool lt( T c1, T c2 ) |
| 37 { |
| 38 return std::tolower( c1 ) < std::tolower( c2 ) ; |
| 39 } |
| 40 |
| 41 /** |
| 42 * Trait comparison function. |
| 43 * |
| 44 * Note that this is not a comparison of C-style strings. |
| 45 * In particular, there's no concern over null characters '\0'. |
| 46 * The argument 'n' is the minimum length of the two strings being compared. |
| 47 * We may assume that the intervals p1[0..n) and p2[0..n) are both valid subst
rings. |
| 48 */ |
| 49 static int compare( const T * p1, const T * p2, size_t n ) |
| 50 { |
| 51 while ( n-- > 0 ) |
| 52 { |
| 53 T l1 = std::tolower( * p1 ++ ) ; |
| 54 T l2 = std::tolower( * p2 ++ ) ; |
| 55 if ( l1 == l2 ) |
| 56 { |
| 57 continue ; |
| 58 } |
| 59 return ( l1 < l2 ) ? -1 : +1 ; |
| 60 } |
| 61 return 0 ; |
| 62 } |
| 63 } ; |
| 64 |
| 65 typedef std::basic_string< wchar_t, ci_traits< wchar_t > > wstring_ci ; |
| 66 |
| 67 //------------------------------------------------------- |
| 68 // file_name_set: case-insensitive wide-string set |
| 69 //------------------------------------------------------- |
| 70 struct file_name_set |
| 71 : public std::set< wstring_ci > |
| 72 { |
| 73 /** |
| 74 * Empty set constructor. |
| 75 */ |
| 76 file_name_set() |
| 77 {} |
| 78 |
| 79 /** |
| 80 * Constructor initialization from an array. |
| 81 */ |
| 82 template< size_t n_file_names > |
| 83 file_name_set( const wchar_t * ( & file_name_list )[ n_file_names ] ) |
| 84 { |
| 85 for ( unsigned int j = 0 ; j < n_file_names ; ++ j ) |
| 86 { |
| 87 insert( wstring_ci( file_name_list[ j ] ) ) ; |
| 88 } |
| 89 } |
| 90 } ; |
| 91 |
| 92 //------------------------------------------------------- |
| 93 //------------------------------------------------------- |
| 94 /** |
| 95 * Filter by process name. Comparison is case-insensitive. With ABP module loade
d |
| 96 */ |
| 97 class process_by_any_exe_with_any_module |
| 98 : public std::binary_function< PROCESSENTRY32W, file_name_set, bool > |
| 99 { |
| 100 /** |
| 101 * Set of file names from which to match candidate process names. |
| 102 * |
| 103 * This is a reference to, not a copy of, the set. |
| 104 * The lifetime of this object must be subordinate to that of its referent. |
| 105 * The set used to instantiate this class is a member of Process_Closer, |
| 106 * and so also is this class. |
| 107 * Hence the lifetimes are coterminous, and the reference is not problematic. |
| 108 */ |
| 109 const file_name_set & processNames ; |
| 110 const file_name_set & moduleNames; |
| 111 public: |
| 112 bool operator()( const PROCESSENTRY32W & ) ; |
| 113 process_by_any_exe_with_any_module( const file_name_set & names, const file_na
me_set & moduleNames ) |
| 114 : processNames( names ), moduleNames( moduleNames ) |
| 115 {} |
| 116 } ; |
| 117 |
| 118 |
| 119 //------------------------------------------------------- |
| 120 // Process utility functions. |
| 121 //------------------------------------------------------- |
| 122 /** |
| 123 * A promiscuous filter admits everything. |
| 124 */ |
| 125 struct every_process |
| 126 : public std::unary_function< PROCESSENTRY32W, bool > |
| 127 { |
| 128 bool operator()( const PROCESSENTRY32W & ) { return true ; } ; |
| 129 } ; |
| 130 |
| 131 /** |
| 132 * Extractor that copies the entire process structure. |
| 133 */ |
| 134 struct copy_all |
| 135 : public std::unary_function< PROCESSENTRY32W, PROCESSENTRY32W > |
| 136 { |
| 137 PROCESSENTRY32W operator()( const PROCESSENTRY32W & process ) { return process
; } |
| 138 } ; |
| 139 |
| 140 /** |
| 141 * Extractor that copies only the PID. |
| 142 */ |
| 143 struct copy_PID |
| 144 : public std::unary_function< PROCESSENTRY32W, DWORD > |
| 145 { |
| 146 inline DWORD operator()( const PROCESSENTRY32W & process ) { return process.th
32ProcessID ; } |
| 147 } ; |
| 148 |
| 149 /** |
| 150 * Retrieve the process ID that created a window. |
| 151 * |
| 152 * Wrapper around GetWindowThreadProcessId. |
| 153 * Converts an error return from the system call into an exception. |
| 154 * The system call can also retrieve the creating thread; we ignore it. |
| 155 * |
| 156 * \param window |
| 157 * Handle of the window |
| 158 * \return |
| 159 * ID of the process that created the argument window |
| 160 * |
| 161 * \sa |
| 162 * MSDN [GetWindowThreadProcessId function](http://msdn.microsoft.com/en-us/li
brary/windows/desktop/ms633522%28v=vs.85%29.aspx) |
| 163 */ |
| 164 DWORD creator_process( HWND window ) ; |
| 165 |
| 166 //------------------------------------------------------- |
| 167 // Snapshot |
| 168 //------------------------------------------------------- |
| 169 /** |
| 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. |
| 235 * |
| 236 * Unfortunately, we cannot provide standard iterator for this class. |
| 237 * Standard iterators must be copy-constructible, which entails the possibility
of multiple, coexisting iteration states. |
| 238 * The iteration behavior provided by Process32First and Process32Next relies up
on state held within the snapshot itself. |
| 239 * Thus, there can be only one iterator at a time for the snapshot. |
| 240 * The two requirements are not simultaneously satisfiable. |
| 241 * |
| 242 * Instead of a standard iterator, we provide a first() and next() functions wra
pping the corresponding system calls. |
| 243 * |
| 244 * \par Implementation |
| 245 * |
| 246 * - MSDN [CreateToolhelp32Snapshot function](http://msdn.microsoft.com/en-us/li
brary/windows/desktop/ms682489%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) |
| 248 * - MSDN [Process32Next function](http://msdn.microsoft.com/en-us/library/windo
ws/desktop/ms684836%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. |
| 257 */ |
| 258 template< class Traits > |
| 259 class Snapshot |
| 260 { |
| 261 public: |
| 262 /** |
| 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. |
| 275 */ |
| 276 Windows_Handle handle ; |
| 277 |
| 278 /** |
| 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. |
| 283 */ |
| 284 result_type buffer; |
| 285 |
| 286 /** |
| 287 * Copy constructor declared private and not defined. |
| 288 * |
| 289 * \par Implementation |
| 290 * Add "= delete" for C++11. |
| 291 */ |
| 292 Snapshot( const Snapshot & ) ; |
| 293 |
| 294 /** |
| 295 * Copy assignment declared private and not defined. |
| 296 * |
| 297 * \par Implementation |
| 298 * Add "= delete" for C++11. |
| 299 */ |
| 300 Snapshot operator=( const Snapshot & ) ; |
| 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 } |
| 325 |
| 326 public: |
| 327 /** |
| 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. |
| 332 */ |
| 333 void refresh() |
| 334 { |
| 335 handle = make_handle(); |
| 336 } |
| 337 |
| 338 /** |
| 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. |
| 353 */ |
| 354 const result_type * first() |
| 355 { |
| 356 return Traits::first(handle, &buffer) ? &buffer : 0; |
| 357 } |
| 358 |
| 359 /** |
| 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. |
| 369 */ |
| 370 const result_type * next() |
| 371 { |
| 372 return Traits::next(handle, &buffer) ? &buffer : 0; |
| 373 } |
| 374 } ; |
| 375 |
| 376 /** |
| 377 * A snapshot of all processes running on the system. |
| 378 */ |
| 379 struct Process_Snapshot |
| 380 : public Snapshot< Process_Snapshot_Traits > |
| 381 { |
| 382 Process_Snapshot() |
| 383 : Snapshot( 0 ) |
| 384 {} |
| 385 } ; |
| 386 |
| 387 /** |
| 388 * A snapshot of all modules loaded for a given process. |
| 389 */ |
| 390 struct Module_Snapshot |
| 391 : public Snapshot< Module_Snapshot_Traits > |
| 392 { |
| 393 Module_Snapshot( DWORD process_id ) |
| 394 : Snapshot( process_id ) |
| 395 {} |
| 396 } ; |
| 397 |
| 398 //------------------------------------------------------- |
| 399 // initialize_process_list |
| 400 //------------------------------------------------------- |
| 401 /** |
| 402 * \tparam T The type into which a PROCESSENTRY32W struture is extracted. |
| 403 * \tparam Admittance Function type for argument 'admit' |
| 404 * \tparam Extractor Function type for argument 'extract' |
| 405 * \param admit A unary predicate function class that determines what's included |
| 406 * A process appears in the list only if the predicate returns true. |
| 407 * The use of this predicate is analogous to that in std::copy_if. |
| 408 * \param convert A conversion function that takes a PROCESSENTRY32W as input ar
gument and returns an element of type T. |
| 409 */ |
| 410 template<class T, class Admittance, class Extractor> |
| 411 void initialize_process_list(std::vector<T>& v, Process_Snapshot &snap, Admittan
ce admit = Admittance(), Extractor extract = Extractor()) |
| 412 { |
| 413 const PROCESSENTRY32W* p = snap.first(); |
| 414 while (p != 0) |
| 415 { |
| 416 if (admit(*p )) |
| 417 { |
| 418 /* |
| 419 * We don't have C++11 emplace_back, which can construct the element in p
lace. |
| 420 * Instead, we copy the return value of the converter. |
| 421 */ |
| 422 v.push_back(extract(*p)); |
| 423 } |
| 424 p = snap.next(); |
| 425 } |
| 426 }; |
| 427 |
| 428 //------------------------------------------------------- |
| 429 // initialize_process_set |
| 430 //------------------------------------------------------- |
| 431 /** |
| 432 * \tparam T The type into which a PROCESSENTRY32W struture is extracted. |
| 433 * \tparam Admittance Function type for argument 'admit' |
| 434 * \tparam Extractor Function type for argument 'extract' |
| 435 * \param admit A unary predicate function class that determines what's included |
| 436 * A process appears in the list only if the predicate returns true. |
| 437 * The use of this predicate is analogous to that in std::copy_if. |
| 438 * \param convert A conversion function that takes a PROCESSENTRY32W as input ar
gument and returns an element of type T. |
| 439 */ |
| 440 template<class T, class Admittance, class Extractor> |
| 441 void initialize_process_set(std::set< T > & set, Process_Snapshot &snap, Admitta
nce admit = Admittance(), Extractor extract = Extractor()) |
| 442 { |
| 443 const PROCESSENTRY32W* p = snap.first(); |
| 444 while (p != 0) |
| 445 { |
| 446 if (admit(*p)) |
| 447 { |
| 448 set.insert(extract(*p)); |
| 449 } |
| 450 p = snap.next(); |
| 451 } |
| 452 }; |
| 453 |
| 454 //------------------------------------------------------- |
| 455 // enumerate_windows |
| 456 //------------------------------------------------------- |
| 457 |
| 458 /** |
| 459 * States of a window enumeration. |
| 460 */ |
| 461 typedef enum |
| 462 { |
| 463 started, ///< The iteration is currently running |
| 464 normal, ///< Iteration terminated without error. |
| 465 early, ///< Callback returned false and terminated iteration early. |
| 466 exception, ///< Callback threw an exception and thereby terminated iterat
ion. |
| 467 error ///< Callback always return true but EnumWindows failed. |
| 468 } enumerate_windows_state ; |
| 469 |
| 470 /** |
| 471 * Data to perform a window enumeration, shared between the main function and th
e callback function. |
| 472 */ |
| 473 template< class F > |
| 474 struct ew_data |
| 475 { |
| 476 /** |
| 477 * Function to be applied to each enumerated window. |
| 478 */ |
| 479 F & f ; |
| 480 |
| 481 /** |
| 482 * Completion status of the enumeration. |
| 483 */ |
| 484 enumerate_windows_state status ; |
| 485 |
| 486 /** |
| 487 * An exception to be transported across the callback. |
| 488 * |
| 489 * The enumerator and the callback are not guaranteed to share a call stack, |
| 490 * nor need they even share compatible exception conventions, |
| 491 * and might not even be in the same thread. |
| 492 * Thus, if the applied function throws an exception, |
| 493 * we catch it in the callback and re-throw it in the enumerator. |
| 494 * This member holds such an exception. |
| 495 * |
| 496 * This member holds an exception only if 'status' has the value 'exception'. |
| 497 * Otherwise it's a null pointer. |
| 498 */ |
| 499 std::unique_ptr< std::exception > ee ; |
| 500 |
| 501 /** |
| 502 * Ordinary constructor. |
| 503 */ |
| 504 ew_data( F & f ) |
| 505 : f( f ), status( started ) |
| 506 {} |
| 507 } ; |
| 508 |
| 509 /** |
| 510 * Callback function for EnumWindows. |
| 511 * |
| 512 * This function provides two standard behaviors. |
| 513 * It records early termination of the enumeration, should that happen by the ap
plied function returning false. |
| 514 * It captures any exception thrown for transport back to the enumerator. |
| 515 */ |
| 516 template< class F > |
| 517 BOOL CALLBACK enumeration_callback( HWND window, LPARAM x ) |
| 518 { |
| 519 // LPARAM is always the same size as a pointer |
| 520 ew_data< F > * data = reinterpret_cast< ew_data< F > * >( x ) ; |
| 521 /* |
| 522 * Top-level try statement prevents exception from propagating back to system. |
| 523 */ |
| 524 try |
| 525 { |
| 526 bool r = data -> f( window ) ; |
| 527 if ( ! r ) |
| 528 { |
| 529 data -> status = early ; |
| 530 } |
| 531 return r ; |
| 532 } |
| 533 catch ( std::exception e ) |
| 534 { |
| 535 data -> ee = std::unique_ptr< std::exception >( new( std::nothrow ) std::exc
eption( e ) ) ; |
| 536 data -> status = exception ; |
| 537 return FALSE ; |
| 538 } |
| 539 catch ( ... ) |
| 540 { |
| 541 data -> ee = std::unique_ptr< std::exception >() ; |
| 542 data -> status = exception ; |
| 543 return FALSE ; |
| 544 } |
| 545 } |
| 546 |
| 547 /** |
| 548 * Enumerate windows, applying a function to each one. |
| 549 */ |
| 550 template< class F > |
| 551 bool enumerate_windows( F f ) |
| 552 { |
| 553 ew_data< F > data( f ) ; |
| 554 BOOL x( ::EnumWindows( enumeration_callback< F >, reinterpret_cast< LPARAM >(
& data ) ) ) ; |
| 555 bool r ; |
| 556 if ( data.status != started ) |
| 557 { |
| 558 // Assert status was changed within the callback |
| 559 if ( data.status == exception ) |
| 560 { |
| 561 /* |
| 562 * The callback threw an exception of some sort. |
| 563 * We forward it to the extent we are able. |
| 564 */ |
| 565 if ( data.ee ) |
| 566 { |
| 567 throw * data.ee ; |
| 568 } |
| 569 else |
| 570 { |
| 571 throw std::runtime_error( "Unknown exception thrown in callback function
." ) ; |
| 572 } |
| 573 } |
| 574 r = false ; |
| 575 } |
| 576 else |
| 577 { |
| 578 if ( x ) |
| 579 { |
| 580 data.status = normal ; |
| 581 r = true ; |
| 582 } |
| 583 else |
| 584 { |
| 585 // Assert EnumWindows failed |
| 586 data.status = error ; |
| 587 r = false ; |
| 588 } |
| 589 } |
| 590 return r ; |
| 591 } |
| 592 |
| 593 //------------------------------------------------------- |
| 594 // Process_Closer |
| 595 //------------------------------------------------------- |
| 596 class Process_Closer |
| 597 { |
| 598 /** |
| 599 * Set of process identifiers matching one of the executable names. |
| 600 */ |
| 601 std::set< DWORD > pid_set ; |
| 602 |
| 603 /** |
| 604 * Set of executable names by which to filter. |
| 605 * |
| 606 * The argument of the filter constructor is a set by reference. |
| 607 * Since it does not make a copy for itself, we define it as a class member to
provide its allocation. |
| 608 */ |
| 609 file_name_set process_names ; |
| 610 |
| 611 /** |
| 612 * Set of module (DLL) names by which to filter. |
| 613 */ |
| 614 file_name_set module_names ; |
| 615 |
| 616 process_by_any_exe_with_any_module filter ; |
| 617 |
| 618 /** |
| 619 * Copy function object copies just the process ID. |
| 620 */ |
| 621 copy_PID copy ; |
| 622 |
| 623 /** |
| 624 * Snapshot of running processes. |
| 625 */ |
| 626 Process_Snapshot & snapshot ; |
| 627 |
| 628 void update() |
| 629 { |
| 630 initialize_process_set( pid_set, snapshot, filter, copy ) ; |
| 631 } ; |
| 632 |
| 633 template< class F > |
| 634 class only_our_processes |
| 635 { |
| 636 Process_Closer & self ; |
| 637 |
| 638 F f ; |
| 639 |
| 640 public: |
| 641 only_our_processes( Process_Closer & self, F f ) |
| 642 : f( f ), self( self ) |
| 643 {} |
| 644 |
| 645 bool operator()( HWND window ) |
| 646 { |
| 647 bool b ; |
| 648 try |
| 649 { |
| 650 b = self.contains( creator_process( window ) ) ; |
| 651 } |
| 652 catch ( ... ) |
| 653 { |
| 654 // ignore window handles that are no longer valid |
| 655 return true ; |
| 656 } |
| 657 if ( ! b ) |
| 658 { |
| 659 // Assert the process that created the window is not in our pid_set |
| 660 return true ; |
| 661 } |
| 662 return f( window ) ; |
| 663 } |
| 664 } ; |
| 665 |
| 666 public: |
| 667 template <size_t n_file_names, size_t 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]) |
| 669 : snapshot(snapshot), process_names(file_name_list), module_names(module_nam
e_list), filter(process_names, module_names) |
| 670 { |
| 671 update() ; |
| 672 } |
| 673 template <size_t n_file_names> |
| 674 Process_Closer(Process_Snapshot & snapshot, const wchar_t * (&file_name_list)[
n_file_names]) |
| 675 : snapshot(snapshot), process_names(file_name_list), module_names(), filter(
process_names, module_names) |
| 676 { |
| 677 update() ; |
| 678 } |
| 679 |
| 680 /** |
| 681 * Refresh our state to match the snapshot state. |
| 682 */ |
| 683 void refresh() |
| 684 { |
| 685 pid_set.clear() ; |
| 686 update() ; |
| 687 } |
| 688 |
| 689 bool is_running() { return ! pid_set.empty() ; } ; |
| 690 |
| 691 bool contains( DWORD pid ) const { return pid_set.find( pid ) != pid_set.end()
; } ; |
| 692 |
| 693 template< class F > |
| 694 bool iterate_our_windows( F f ) |
| 695 { |
| 696 only_our_processes< F > g( * this, f ) ; |
| 697 return enumerate_windows( g ) ; |
| 698 } |
| 699 |
| 700 /* |
| 701 * Shut down every process in the pid_set. |
| 702 */ |
| 703 bool shut_down() ; |
| 704 |
| 705 } ; |
| 706 |
| 707 #endif |
OLD | NEW |