| 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 "installer-lib.h" | 
| 9 #include "handle.h" | 9 #include "handle.h" | 
| 10 | 10 | 
| 11 #include <string> | 11 #include <string> | 
| 12 #include <cctype> | 12 #include <cctype> | 
| 13 #include <vector> | 13 #include <vector> | 
| 14 #include <set> | 14 #include <set> | 
| 15 #include <algorithm> | 15 #include <algorithm> | 
| 16 #include <memory> | 16 #include <memory> | 
| 17 | 17 | 
| 18 #include <Windows.h> | 18 #include <Windows.h> | 
| 19 #include <TlHelp32.h> | 19 #include <TlHelp32.h> | 
| 20 | 20 | 
| 21 //------------------------------------------------------- | 21 //------------------------------------------------------- | 
| 22 // wstring_ci: case-insensitive wide string | 22 // WstringCaseInsensitive: case-insensitive wide string | 
| 23 //------------------------------------------------------- | 23 //------------------------------------------------------- | 
| 24 | 24 | 
| 25 /** | 25 /** | 
| 26  * Traits class for case-insensitive strings. | 26  * Traits class for case-insensitive strings. | 
| 27  */ | 27  */ | 
| 28 template< class T > | 28 template< class T > | 
| 29 struct ci_traits: std::char_traits< T > | 29 struct CaseInsensitiveTraits: std::char_traits< T > | 
| 30 { | 30 { | 
| 31   static bool eq( T c1, T c2 ) | 31   static bool eq( T c1, T c2 ) | 
| 32   { | 32   { | 
| 33     return std::tolower( c1 ) == std::tolower( c2 ) ; | 33     return std::tolower( c1 ) == std::tolower( c2 ) ; | 
| 34   } | 34   } | 
| 35 | 35 | 
| 36   static bool lt( T c1, T c2 ) | 36   static bool lt( T c1, T c2 ) | 
| 37   { | 37   { | 
| 38     return std::tolower( c1 ) < std::tolower( c2 ) ; | 38     return std::tolower( c1 ) < std::tolower( c2 ) ; | 
| 39   } | 39   } | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
| 55       if ( l1 == l2 ) | 55       if ( l1 == l2 ) | 
| 56       { | 56       { | 
| 57         continue ; | 57         continue ; | 
| 58       } | 58       } | 
| 59       return ( l1 < l2 ) ? -1 : +1 ; | 59       return ( l1 < l2 ) ? -1 : +1 ; | 
| 60     } | 60     } | 
| 61     return 0  ; | 61     return 0  ; | 
| 62   } | 62   } | 
| 63 } ; | 63 } ; | 
| 64 | 64 | 
| 65 typedef std::basic_string< wchar_t, ci_traits< wchar_t > > wstring_ci ; | 65 typedef std::basic_string< wchar_t, CaseInsensitiveTraits< wchar_t > > WstringCa
     seInsensitive ; | 
| 66 | 66 | 
| 67 //------------------------------------------------------- | 67 //------------------------------------------------------- | 
| 68 // file_name_set: case-insensitive wide-string set | 68 // FileNameSet: case-insensitive wide-string set | 
| 69 //------------------------------------------------------- | 69 //------------------------------------------------------- | 
| 70 struct file_name_set | 70 struct FileNameSet | 
| 71   : public std::set< wstring_ci > | 71   : public std::set< WstringCaseInsensitive > | 
| 72 { | 72 { | 
| 73   /** | 73   /** | 
| 74    * Empty set constructor. | 74    * Empty set constructor. | 
| 75    */ | 75    */ | 
| 76   file_name_set() | 76   FileNameSet() | 
| 77   {} | 77   {} | 
| 78 | 78 | 
| 79   /** | 79   /** | 
| 80    * Constructor initialization from an array. | 80    * Constructor initialization from an array. | 
| 81    */ | 81    */ | 
| 82   template< size_t n_file_names > | 82   template< size_t nFileNames > | 
| 83   file_name_set( const wchar_t * ( & file_name_list )[ n_file_names ] ) | 83   FileNameSet( const wchar_t * ( & fileNameList )[ nFileNames ] ) | 
| 84   { | 84   { | 
| 85     for ( unsigned int j = 0 ; j < n_file_names ; ++ j ) | 85     for ( unsigned int j = 0 ; j < nFileNames ; ++ j ) | 
| 86     { | 86     { | 
| 87       insert( wstring_ci( file_name_list[ j ] ) ) ; | 87       insert( WstringCaseInsensitive( fileNameList[ j ] ) ) ; | 
| 88     } | 88     } | 
| 89   } | 89   } | 
| 90 } ; | 90 } ; | 
| 91 | 91 | 
| 92 //------------------------------------------------------- | 92 //------------------------------------------------------- | 
| 93 //------------------------------------------------------- | 93 //------------------------------------------------------- | 
| 94 /** | 94 /** | 
| 95  * Filter by process name. Comparison is case-insensitive. Windows Store app pro
     cesses excluded | 95  * Filter by process name. Comparison is case-insensitive. Windows Store app pro
     cesses excluded | 
| 96  */ | 96  */ | 
| 97 class process_by_any_exe_not_immersive | 97 class ProcessByAnyExeNotImmersive | 
| 98   : public std::unary_function<PROCESSENTRY32W, bool> | 98   : public std::unary_function<PROCESSENTRY32W, bool> | 
| 99 { | 99 { | 
| 100   /** | 100   /** | 
| 101    * Set of file names from which to match candidate process names. | 101    * Set of file names from which to match candidate process names. | 
| 102    * | 102    * | 
| 103    * This is a reference to, not a copy of, the set. | 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. | 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 ProcessCloser, | 105    * The set used to instantiate this class is a member of ProcessCloser, | 
| 106    *   and so also is this class. | 106    *   and so also is this class. | 
| 107    * Hence the lifetimes are coterminous, and the reference is not problematic. | 107    * Hence the lifetimes are coterminous, and the reference is not problematic. | 
| 108    */ | 108    */ | 
| 109   const file_name_set & processNames; | 109   const FileNameSet & processNames; | 
| 110 public: | 110 public: | 
| 111   bool operator()( const PROCESSENTRY32W & ); | 111   bool operator()( const PROCESSENTRY32W & ); | 
| 112   process_by_any_exe_not_immersive(const file_name_set & names) : processNames( 
     names ) {} | 112   ProcessByAnyExeNotImmersive(const FileNameSet & names) : processNames( names )
      {} | 
| 113 } ; | 113 } ; | 
| 114 | 114 | 
| 115 | 115 | 
| 116 //------------------------------------------------------- | 116 //------------------------------------------------------- | 
| 117 // Process utility functions. | 117 // Process utility functions. | 
| 118 //------------------------------------------------------- | 118 //------------------------------------------------------- | 
| 119 /** | 119 /** | 
| 120  * A promiscuous filter admits everything. | 120  * A promiscuous filter admits everything. | 
| 121  */ | 121  */ | 
| 122 struct every_process | 122 struct EveryProcess | 
| 123   : public std::unary_function< PROCESSENTRY32W, bool > | 123   : public std::unary_function< PROCESSENTRY32W, bool > | 
| 124 { | 124 { | 
| 125   bool operator()( const PROCESSENTRY32W & ) { return true ; } ; | 125   bool operator()( const PROCESSENTRY32W & ) { return true ; } ; | 
| 126 } ; | 126 } ; | 
| 127 | 127 | 
| 128 /** | 128 /** | 
| 129  * Extractor that copies the entire process structure. | 129  * Extractor that copies the entire process structure. | 
| 130  */ | 130  */ | 
| 131 struct copy_all | 131 struct CopyAll | 
| 132   : public std::unary_function< PROCESSENTRY32W, PROCESSENTRY32W > | 132   : public std::unary_function< PROCESSENTRY32W, PROCESSENTRY32W > | 
| 133 { | 133 { | 
| 134   PROCESSENTRY32W operator()( const PROCESSENTRY32W & process ) { return process
      ; } | 134   PROCESSENTRY32W operator()( const PROCESSENTRY32W & process ) { return process
      ; } | 
| 135 } ; | 135 } ; | 
| 136 | 136 | 
| 137 /** | 137 /** | 
| 138  * Extractor that copies only the PID. | 138  * Extractor that copies only the PID. | 
| 139  */ | 139  */ | 
| 140 struct copy_PID | 140 struct CopyPID | 
| 141   : public std::unary_function< PROCESSENTRY32W, DWORD > | 141   : public std::unary_function< PROCESSENTRY32W, DWORD > | 
| 142 { | 142 { | 
| 143   inline DWORD operator()( const PROCESSENTRY32W & process ) { return process.th
     32ProcessID ; } | 143   inline DWORD operator()( const PROCESSENTRY32W & process ) { return process.th
     32ProcessID ; } | 
| 144 } ; | 144 } ; | 
| 145 | 145 | 
| 146 /** | 146 /** | 
| 147  * Retrieve the process ID that created a window. | 147  * Retrieve the process ID that created a window. | 
| 148  * | 148  * | 
| 149  * Wrapper around GetWindowThreadProcessId. | 149  * Wrapper around GetWindowThreadProcessId. | 
| 150  * Converts an error return from the system call into an exception. | 150  * Converts an error return from the system call into an exception. | 
| 151  * The system call can also retrieve the creating thread; we ignore it. | 151  * The system call can also retrieve the creating thread; we ignore it. | 
| 152  * | 152  * | 
| 153  * \param window | 153  * \param window | 
| 154  *   Handle of the window | 154  *   Handle of the window | 
| 155  * \return | 155  * \return | 
| 156  *   ID of the process that created the argument window | 156  *   ID of the process that created the argument window | 
| 157  * | 157  * | 
| 158  * \sa | 158  * \sa | 
| 159  *   MSDN [GetWindowThreadProcessId function](http://msdn.microsoft.com/en-us/li
     brary/windows/desktop/ms633522%28v=vs.85%29.aspx) | 159  *   MSDN [GetWindowThreadProcessId function](http://msdn.microsoft.com/en-us/li
     brary/windows/desktop/ms633522%28v=vs.85%29.aspx) | 
| 160  */ | 160  */ | 
| 161 DWORD creator_process( HWND window ) ; | 161 DWORD CreatorProcess( HWND window ) ; | 
| 162 | 162 | 
| 163 //------------------------------------------------------- | 163 //------------------------------------------------------- | 
| 164 // Snapshot | 164 // Snapshot | 
| 165 //------------------------------------------------------- | 165 //------------------------------------------------------- | 
| 166 /** | 166 /** | 
| 167  * Traits class for snapshots of all processes on the system. | 167  * Traits class for snapshots of all processes on the system. | 
| 168  */ | 168  */ | 
| 169 struct Process_Snapshot_Traits | 169 struct ProcessSnapshotTraits | 
| 170 { | 170 { | 
| 171   /** | 171   /** | 
| 172    * The type of the data resulting from CreateToolhelp32Snapshot. | 172    * The type of the data resulting from CreateToolhelp32Snapshot. | 
| 173    */ | 173    */ | 
| 174   typedef PROCESSENTRY32W result_type ; | 174   typedef PROCESSENTRY32W ResultType ; | 
| 175 | 175 | 
| 176   /** | 176   /** | 
| 177    * Flags used to call CreateToolhelp32Snapshot. | 177    * Flags used to call CreateToolhelp32Snapshot. | 
| 178    */ | 178    */ | 
| 179   const static DWORD snapshot_flags = TH32CS_SNAPPROCESS ; | 179   const static DWORD SnapshotFlags = TH32CS_SNAPPROCESS ; | 
| 180 | 180 | 
| 181   /** | 181   /** | 
| 182    * Wrapper for 'first' function for processes | 182    * Wrapper for 'first' function for processes | 
| 183    */ | 183    */ | 
| 184   static BOOL first( HANDLE arg1, LPPROCESSENTRY32 arg2 ) | 184   static BOOL First( HANDLE arg1, LPPROCESSENTRY32 arg2 ) | 
| 185   { | 185   { | 
| 186     return ::Process32First( arg1, arg2 ) ; | 186     return ::Process32First( arg1, arg2 ) ; | 
| 187   } | 187   } | 
| 188 | 188 | 
| 189   /** | 189   /** | 
| 190    * Wrapper for 'next' function for processes | 190    * Wrapper for 'next' function for processes | 
| 191    */ | 191    */ | 
| 192   static BOOL next( HANDLE arg1, LPPROCESSENTRY32 arg2 ) | 192   static BOOL Next( HANDLE arg1, LPPROCESSENTRY32 arg2 ) | 
| 193   { | 193   { | 
| 194     return ::Process32Next( arg1, arg2 ) ; | 194     return ::Process32Next( arg1, arg2 ) ; | 
| 195   } | 195   } | 
| 196 } ; | 196 } ; | 
| 197 | 197 | 
| 198 /** | 198 /** | 
| 199  * Traits class for snapshots of all modules loaded by a process. | 199  * Traits class for snapshots of all modules loaded by a process. | 
| 200  */ | 200  */ | 
| 201 struct Module_Snapshot_Traits | 201 struct ModuleSnapshotTraits | 
| 202 { | 202 { | 
| 203   /** | 203   /** | 
| 204    * The type of the data resulting from CreateToolhelp32Snapshot. | 204    * The type of the data resulting from CreateToolhelp32Snapshot. | 
| 205    */ | 205    */ | 
| 206   typedef MODULEENTRY32W result_type ; | 206   typedef MODULEENTRY32W ResultType ; | 
| 207 | 207 | 
| 208   /** | 208   /** | 
| 209    * Flags used to call CreateToolhelp32Snapshot. | 209    * Flags used to call CreateToolhelp32Snapshot. | 
| 210    */ | 210    */ | 
| 211   const static DWORD snapshot_flags = TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32 ; | 211   const static DWORD SnapshotFlags = TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32 ; | 
| 212 | 212 | 
| 213   /** | 213   /** | 
| 214    * Wrapper for 'first' function for modules | 214    * Wrapper for 'first' function for modules | 
| 215    */ | 215    */ | 
| 216   static BOOL first( HANDLE arg1, LPMODULEENTRY32 arg2 ) | 216   static BOOL First( HANDLE arg1, LPMODULEENTRY32 arg2 ) | 
| 217   { | 217   { | 
| 218     return ::Module32First( arg1, arg2 ) ; | 218     return ::Module32First( arg1, arg2 ) ; | 
| 219   } | 219   } | 
| 220 | 220 | 
| 221   /** | 221   /** | 
| 222    * Wrapper for 'next' function for modules | 222    * Wrapper for 'next' function for modules | 
| 223    */ | 223    */ | 
| 224   static BOOL next( HANDLE arg1, LPMODULEENTRY32 arg2 ) | 224   static BOOL Next( HANDLE arg1, LPMODULEENTRY32 arg2 ) | 
| 225   { | 225   { | 
| 226     return ::Module32Next( arg1, arg2 ) ; | 226     return ::Module32Next( arg1, arg2 ) ; | 
| 227   } | 227   } | 
| 228 } ; | 228 } ; | 
| 229 | 229 | 
| 230 /** | 230 /** | 
| 231  * A snapshot wrapping the results of CreateToolhelp32Snapshot system call. | 231  * A snapshot wrapping the results of CreateToolhelp32Snapshot system call. | 
| 232  * | 232  * | 
| 233  * Unfortunately, we cannot provide standard iterator for this class. | 233  * Unfortunately, we cannot provide standard iterator for this class. | 
| 234  * Standard iterators must be copy-constructible, which entails the possibility 
     of multiple, coexisting iteration states. | 234  * Standard iterators must be copy-constructible, which entails the possibility 
     of multiple, coexisting iteration states. | 
| 235  * The iteration behavior provided by Process32First and Process32Next relies up
     on state held within the snapshot itself. | 235  * The iteration behavior provided by Process32First and Process32Next relies up
     on state held within the snapshot itself. | 
| 236  * Thus, there can be only one iterator at a time for the snapshot. | 236  * Thus, there can be only one iterator at a time for the snapshot. | 
| 237  * The two requirements are not simultaneously satisfiable. | 237  * The two requirements are not simultaneously satisfiable. | 
| 238  * | 238  * | 
| 239  * Instead of a standard iterator, we provide a first() and next() functions wra
     pping the corresponding system calls. | 239  * Instead of a standard iterator, we provide a First() and Next() functions wra
     pping the corresponding system calls. | 
| 240  * | 240  * | 
| 241  * \par Implementation | 241  * \par Implementation | 
| 242  * | 242  * | 
| 243  * - MSDN [CreateToolhelp32Snapshot function](http://msdn.microsoft.com/en-us/li
     brary/windows/desktop/ms682489%28v=vs.85%29.aspx) | 243  * - MSDN [CreateToolhelp32Snapshot function](http://msdn.microsoft.com/en-us/li
     brary/windows/desktop/ms682489%28v=vs.85%29.aspx) | 
| 244  * - MSDN [Process32First function](http://msdn.microsoft.com/en-us/library/wind
     ows/desktop/ms684834%28v=vs.85%29.aspx) | 244  * - MSDN [Process32First function](http://msdn.microsoft.com/en-us/library/wind
     ows/desktop/ms684834%28v=vs.85%29.aspx) | 
| 245  * - MSDN [Process32Next function](http://msdn.microsoft.com/en-us/library/windo
     ws/desktop/ms684836%28v=vs.85%29.aspx) | 245  * - MSDN [Process32Next function](http://msdn.microsoft.com/en-us/library/windo
     ws/desktop/ms684836%28v=vs.85%29.aspx) | 
| 246  * - MSDN [PROCESSENTRY32 structure](http://msdn.microsoft.com/en-us/library/win
     dows/desktop/ms684839%28v=vs.85%29.aspx) | 246  * - MSDN [PROCESSENTRY32 structure](http://msdn.microsoft.com/en-us/library/win
     dows/desktop/ms684839%28v=vs.85%29.aspx) | 
| 247  * | 247  * | 
| 248  * \par Design Note | 248  * \par Design Note | 
| 249  *   The traits class defines first() and next() functions instead of using func
     tion pointers. | 249  *   The traits class defines First() and Next() functions instead of using func
     tion pointers. | 
| 250  *   This arises from a limitation in the compiler. | 250  *   This arises from a limitation in the compiler. | 
| 251  *   The system calls are declared 'WINAPI', which is a compiler-specific extens
     ion. | 251  *   The system calls are declared 'WINAPI', which is a compiler-specific extens
     ion. | 
| 252  *   That extension, however, does not go far enough to be able to declare a poi
     nter with the same modifier. | 252  *   That extension, however, does not go far enough to be able to declare a poi
     nter with the same modifier. | 
| 253  *   Hence the system calls must be called directly; they are wrapped in the tra
     it functions. | 253  *   Hence the system calls must be called directly; they are wrapped in the tra
     it functions. | 
| 254  */ | 254  */ | 
| 255 template< class Traits > | 255 template< class Traits > | 
| 256 class Snapshot | 256 class Snapshot | 
| 257 { | 257 { | 
| 258 public: | 258 public: | 
| 259   /** | 259   /** | 
| 260    * Expose the result type from the traits class as our own. | 260    * Expose the result type from the traits class as our own. | 
| 261    */ | 261    */ | 
| 262   typedef typename Traits::result_type result_type ; | 262   typedef typename Traits::ResultType ResultType ; | 
| 263 | 263 | 
| 264 private: | 264 private: | 
| 265   /** | 265   /** | 
| 266    * Process ID argument for CreateToolhelp32Snapshot. | 266    * Process ID argument for CreateToolhelp32Snapshot. | 
| 267    */ | 267    */ | 
| 268   DWORD _id ; | 268   DWORD id ; | 
| 269 | 269 | 
| 270   /** | 270   /** | 
| 271    * Handle to the underlying snapshot. | 271    * Handle to the underlying snapshot. | 
| 272    */ | 272    */ | 
| 273   Windows_Handle handle ; | 273   WindowsHandle handle ; | 
| 274 | 274 | 
| 275   /** | 275   /** | 
| 276    * Buffer for reading a single process entry out of the snapshot. | 276    * Buffer for reading a single process entry out of the snapshot. | 
| 277    * | 277    * | 
| 278    * This buffer is constant insofar as the code outside this class is concerned
     . | 278    * This buffer is constant insofar as the code outside this class is concerned
     . | 
| 279    * The accessor functions first() and next() return pointers to constant resul
     t_type. | 279    * The accessor functions First() and Next() return pointers to constant Resul
     tType. | 
| 280    */ | 280    */ | 
| 281   result_type buffer; | 281   ResultType buffer; | 
| 282 | 282 | 
| 283   /** | 283   /** | 
| 284    * Copy constructor declared private and not defined. | 284    * Copy constructor declared private and not defined. | 
| 285    * | 285    * | 
| 286    * \par Implementation | 286    * \par Implementation | 
| 287    *   Add "= delete" for C++11. | 287    *   Add "= delete" for C++11. | 
| 288    */ | 288    */ | 
| 289   Snapshot( const Snapshot & ) ; | 289   Snapshot( const Snapshot & ) ; | 
| 290 | 290 | 
| 291   /** | 291   /** | 
| 292    * Copy assignment declared private and not defined. | 292    * Copy assignment declared private and not defined. | 
| 293    * | 293    * | 
| 294    * \par Implementation | 294    * \par Implementation | 
| 295    *   Add "= delete" for C++11. | 295    *   Add "= delete" for C++11. | 
| 296    */ | 296    */ | 
| 297   Snapshot operator=( const Snapshot & ) ; | 297   Snapshot operator=( const Snapshot & ) ; | 
| 298 | 298 | 
| 299   /** | 299   /** | 
| 300    * Create a new snapshot and return its handle. | 300    * Create a new snapshot and return its handle. | 
| 301    */ | 301    */ | 
| 302   Windows_Handle::handle_type make_handle() | 302   WindowsHandle::HandleType MakeHandle() | 
| 303   { | 303   { | 
| 304     Windows_Handle::handle_type h = ::CreateToolhelp32Snapshot( Traits::snapshot
     _flags, _id ) ; | 304     WindowsHandle::HandleType h = ::CreateToolhelp32Snapshot( Traits::SnapshotFl
     ags, id ) ; | 
| 305     if ( h == INVALID_HANDLE_VALUE ) | 305     if ( h == INVALID_HANDLE_VALUE ) | 
| 306     { | 306     { | 
| 307       throw windows_api_error( "CreateToolhelp32Snapshot", "INVALID_HANDLE_VALUE
     " ) ; | 307       throw WindowsApiError( "CreateToolhelp32Snapshot", "INVALID_HANDLE_VALUE" 
     ) ; | 
| 308     } | 308     } | 
| 309     return h ; | 309     return h ; | 
| 310   } | 310   } | 
| 311 | 311 | 
| 312 protected: | 312 protected: | 
| 313   /** | 313   /** | 
| 314    * Constructor takes a snapshot. | 314    * Constructor takes a snapshot. | 
| 315    */ | 315    */ | 
| 316   Snapshot( DWORD id ) | 316   Snapshot( DWORD id ) | 
| 317     : _id( id ), handle( make_handle() ) | 317     : id( id ), handle( MakeHandle() ) | 
| 318   { | 318   { | 
| 319     // The various result types all define 'dwSize' with the same semantics. | 319     // The various result types all define 'dwSize' with the same semantics. | 
| 320     buffer.dwSize = sizeof( result_type ) ; | 320     buffer.dwSize = sizeof( ResultType ) ; | 
| 321   } | 321   } | 
| 322 | 322 | 
| 323 public: | 323 public: | 
| 324   /** | 324   /** | 
| 325    * Reconstruct the current instance with a new system snapshot. | 325    * Reconstruct the current instance with a new system snapshot. | 
| 326    * | 326    * | 
| 327    * This function uses reinitialization assignment in the Windows_Handle class, | 327    * This function uses reinitialization assignment in the WindowsHandle class, | 
| 328    *   which takes care of closing the old handle. | 328    *   which takes care of closing the old handle. | 
| 329    */ | 329    */ | 
| 330   void Refresh() | 330   void Refresh() | 
| 331   { | 331   { | 
| 332     handle = make_handle(); | 332     handle = MakeHandle(); | 
| 333   } | 333   } | 
| 334 | 334 | 
| 335   /** | 335   /** | 
| 336    * Retrieve the first snapshot item into our member buffer. | 336    * Retrieve the first snapshot item into our member buffer. | 
| 337    * | 337    * | 
| 338    * \return | 338    * \return | 
| 339    *   Pointer to our member buffer if there was a first item | 339    *   Pointer to our member buffer if there was a first item | 
| 340    *   0 otherwise | 340    *   0 otherwise | 
| 341    * | 341    * | 
| 342    * \par Design Note | 342    * \par Design Note | 
| 343    *   There's no error handling in the present version of this function. | 343    *   There's no error handling in the present version of this function. | 
| 344    *   In part that's because the underlying system call returns either true or 
     false, both of which are ordinarily valid answers. | 344    *   In part that's because the underlying system call returns either true or 
     false, both of which are ordinarily valid answers. | 
| 345    *   The trouble is that a false return is overloaded. | 345    *   The trouble is that a false return is overloaded. | 
| 346    *   It can mean either that (ordinary) there are no more items or (exceptiona
     l) the snapshot did not contain the right kind of item. | 346    *   It can mean either that (ordinary) there are no more items or (exceptiona
     l) the snapshot did not contain the right kind of item. | 
| 347    *   GetLastError is no help here; it doesn't distinguish between these cases. | 347    *   GetLastError is no help here; it doesn't distinguish between these cases. | 
| 348    *   The upshot is that we rely that our implementation calls the right functi
     ons on the snapshot, | 348    *   The upshot is that we rely that our implementation calls the right functi
     ons on the snapshot, | 
| 349    *     and so we ignore the case where we've passed bad arguments to the syste
     m call. | 349    *     and so we ignore the case where we've passed bad arguments to the syste
     m call. | 
| 350    */ | 350    */ | 
| 351   const result_type * first() | 351   const ResultType * First() | 
| 352   { | 352   { | 
| 353     return Traits::first(handle, &buffer) ? &buffer : 0; | 353     return Traits::First(handle, &buffer) ? &buffer : 0; | 
| 354   } | 354   } | 
| 355 | 355 | 
| 356   /** | 356   /** | 
| 357    * Retrieve the next snapshot item into our member buffer and return a pointer
      to it. | 357    * Retrieve the next snapshot item into our member buffer and return a pointer
      to it. | 
| 358    * begin() must have been called first. | 358    * begin() must have been called first. | 
| 359    * | 359    * | 
| 360    * \return | 360    * \return | 
| 361    *   Pointer to our member buffer if there was a first item | 361    *   Pointer to our member buffer if there was a first item | 
| 362    *   0 otherwise | 362    *   0 otherwise | 
| 363    * | 363    * | 
| 364    * \par Design Note | 364    * \par Design Note | 
| 365    *   See the Design Note for first(); the same considerations apply here. | 365    *   See the Design Note for First(); the same considerations apply here. | 
| 366    */ | 366    */ | 
| 367   const result_type * next() | 367   const ResultType * Next() | 
| 368   { | 368   { | 
| 369     return Traits::next(handle, &buffer) ? &buffer : 0; | 369     return Traits::Next(handle, &buffer) ? &buffer : 0; | 
| 370   } | 370   } | 
| 371 } ; | 371 } ; | 
| 372 | 372 | 
| 373 /** | 373 /** | 
| 374  * A snapshot of all processes running on the system. | 374  * A snapshot of all processes running on the system. | 
| 375  */ | 375  */ | 
| 376 struct ProcessSnapshot | 376 struct ProcessSnapshot | 
| 377   : public Snapshot< Process_Snapshot_Traits > | 377   : public Snapshot< ProcessSnapshotTraits > | 
| 378 { | 378 { | 
| 379   ProcessSnapshot() | 379   ProcessSnapshot() | 
| 380     : Snapshot( 0 ) | 380     : Snapshot( 0 ) | 
| 381   {} | 381   {} | 
| 382 } ; | 382 } ; | 
| 383 | 383 | 
| 384 /** | 384 /** | 
| 385  * A snapshot of all modules loaded for a given process. | 385  * A snapshot of all modules loaded for a given process. | 
| 386  */ | 386  */ | 
| 387 struct Module_Snapshot | 387 struct ModuleSnapshot | 
| 388   : public Snapshot< Module_Snapshot_Traits > | 388   : public Snapshot< ModuleSnapshotTraits > | 
| 389 { | 389 { | 
| 390   Module_Snapshot( DWORD process_id ) | 390   ModuleSnapshot( DWORD processId ) | 
| 391     : Snapshot( process_id ) | 391     : Snapshot( processId ) | 
| 392   {} | 392   {} | 
| 393 } ; | 393 } ; | 
| 394 | 394 | 
| 395 //------------------------------------------------------- | 395 //------------------------------------------------------- | 
| 396 // initialize_process_list | 396 // InitializeProcessList | 
| 397 //------------------------------------------------------- | 397 //------------------------------------------------------- | 
| 398 /** | 398 /** | 
| 399  * \tparam T The type into which a PROCESSENTRY32W struture is extracted. | 399  * \tparam T The type into which a PROCESSENTRY32W struture is extracted. | 
| 400  * \tparam Admittance Function type for argument 'admit' | 400  * \tparam Admittance Function type for argument 'admit' | 
| 401  * \tparam Extractor Function type for argument 'extract' | 401  * \tparam Extractor Function type for argument 'extract' | 
| 402  * \param admit A unary predicate function class that determines what's included | 402  * \param admit A unary predicate function class that determines what's included | 
| 403  *      A process appears in the list only if the predicate returns true. | 403  *      A process appears in the list only if the predicate returns true. | 
| 404  *      The use of this predicate is analogous to that in std::copy_if. | 404  *      The use of this predicate is analogous to that in std::copy_if. | 
| 405  * \param convert A conversion function that takes a PROCESSENTRY32W as input ar
     gument and returns an element of type T. | 405  * \param convert A conversion function that takes a PROCESSENTRY32W as input ar
     gument and returns an element of type T. | 
| 406  */ | 406  */ | 
| 407 template<class T, class Admittance, class Extractor> | 407 template<class T, class Admittance, class Extractor> | 
| 408 void initialize_process_list(std::vector<T>& v, ProcessSnapshot &snap, Admittanc
     e admit = Admittance(), Extractor extract = Extractor()) | 408 void InitializeProcessList(std::vector<T>& v, ProcessSnapshot &snap, Admittance 
     admit = Admittance(), Extractor extract = Extractor()) | 
| 409 { | 409 { | 
| 410   const PROCESSENTRY32W* p = snap.first(); | 410   const PROCESSENTRY32W* p = snap.First(); | 
| 411   while (p != 0) | 411   while (p != 0) | 
| 412   { | 412   { | 
| 413     if (admit(*p )) | 413     if (admit(*p )) | 
| 414     { | 414     { | 
| 415       /* | 415       /* | 
| 416 »       * We don't have C++11 emplace_back, which can construct the element in p
     lace. | 416        * We don't have C++11 emplace_back, which can construct the element in pl
     ace. | 
| 417 »       * Instead, we copy the return value of the converter. | 417        * Instead, we copy the return value of the converter. | 
| 418 »       */ | 418        */ | 
| 419       v.push_back(extract(*p)); | 419       v.push_back(extract(*p)); | 
| 420     } | 420     } | 
| 421     p = snap.next(); | 421     p = snap.Next(); | 
| 422   } | 422   } | 
| 423 }; | 423 }; | 
| 424 | 424 | 
| 425 //------------------------------------------------------- | 425 //------------------------------------------------------- | 
| 426 // initialize_process_set | 426 // InitializeProcessSet | 
| 427 //------------------------------------------------------- | 427 //------------------------------------------------------- | 
| 428 /** | 428 /** | 
| 429  * \tparam T The type into which a PROCESSENTRY32W struture is extracted. | 429  * \tparam T The type into which a PROCESSENTRY32W struture is extracted. | 
| 430  * \tparam Admittance Function type for argument 'admit' | 430  * \tparam Admittance Function type for argument 'admit' | 
| 431  * \tparam Extractor Function type for argument 'extract' | 431  * \tparam Extractor Function type for argument 'extract' | 
| 432  * \param admit A unary predicate function class that determines what's included | 432  * \param admit A unary predicate function class that determines what's included | 
| 433  *      A process appears in the list only if the predicate returns true. | 433  *      A process appears in the list only if the predicate returns true. | 
| 434  *      The use of this predicate is analogous to that in std::copy_if. | 434  *      The use of this predicate is analogous to that in std::copy_if. | 
| 435  * \param convert A conversion function that takes a PROCESSENTRY32W as input ar
     gument and returns an element of type T. | 435  * \param convert A conversion function that takes a PROCESSENTRY32W as input ar
     gument and returns an element of type T. | 
| 436  */ | 436  */ | 
| 437 template<class T, class Admittance, class Extractor> | 437 template<class T, class Admittance, class Extractor> | 
| 438 void initialize_process_set(std::set< T > & set, ProcessSnapshot &snap, Admittan
     ce admit = Admittance(), Extractor extract = Extractor()) | 438 void InitializeProcessSet(std::set< T > & set, ProcessSnapshot &snap, Admittance
      admit = Admittance(), Extractor extract = Extractor()) | 
| 439 { | 439 { | 
| 440   const PROCESSENTRY32W* p = snap.first(); | 440   const PROCESSENTRY32W* p = snap.First(); | 
| 441   while (p != 0) | 441   while (p != 0) | 
| 442   { | 442   { | 
| 443     if (admit(*p)) | 443     if (admit(*p)) | 
| 444     { | 444     { | 
| 445       set.insert(extract(*p)); | 445       set.insert(extract(*p)); | 
| 446     } | 446     } | 
| 447     p = snap.next(); | 447     p = snap.Next(); | 
| 448   } | 448   } | 
| 449 }; | 449 }; | 
| 450 | 450 | 
| 451 //------------------------------------------------------- | 451 //------------------------------------------------------- | 
| 452 // enumerate_windows | 452 // EnumerateWindows | 
| 453 //------------------------------------------------------- | 453 //------------------------------------------------------- | 
| 454 | 454 | 
| 455 /** | 455 /** | 
| 456  * States of a window enumeration. | 456  * States of a window enumeration. | 
| 457  */ | 457  */ | 
| 458 typedef enum | 458 typedef enum | 
| 459 { | 459 { | 
| 460   started,        ///< The iteration is currently running | 460   started,        ///< The iteration is currently running | 
| 461   normal,         ///< Iteration terminated without error. | 461   normal,         ///< Iteration terminated without error. | 
| 462   early,          ///< Callback returned false and terminated iteration early. | 462   early,          ///< Callback returned false and terminated iteration early. | 
| 463   exception,      ///< Callback threw an exception and thereby terminated iterat
     ion. | 463   exception,      ///< Callback threw an exception and thereby terminated iterat
     ion. | 
| 464   error           ///< Callback always return true but EnumWindows failed. | 464   error           ///< Callback always return true but EnumWindows failed. | 
| 465 } enumerate_windows_state ; | 465 } EnumerateWindowsState ; | 
| 466 | 466 | 
| 467 /** | 467 /** | 
| 468  * Data to perform a window enumeration, shared between the main function and th
     e callback function. | 468  * Data to perform a window enumeration, shared between the main function and th
     e callback function. | 
| 469  */ | 469  */ | 
| 470 template< class F > | 470 template< class F > | 
| 471 struct ew_data | 471 struct EWData | 
| 472 { | 472 { | 
| 473   /** | 473   /** | 
| 474    * Function to be applied to each enumerated window. | 474    * Function to be applied to each enumerated window. | 
| 475    */ | 475    */ | 
| 476   F & f ; | 476   F & f ; | 
| 477 | 477 | 
| 478   /** | 478   /** | 
| 479    * Completion status of the enumeration. | 479    * Completion status of the enumeration. | 
| 480    */ | 480    */ | 
| 481   enumerate_windows_state status ; | 481   EnumerateWindowsState status ; | 
| 482 | 482 | 
| 483   /** | 483   /** | 
| 484    * An exception to be transported across the callback. | 484    * An exception to be transported across the callback. | 
| 485    * | 485    * | 
| 486    * The enumerator and the callback are not guaranteed to share a call stack, | 486    * The enumerator and the callback are not guaranteed to share a call stack, | 
| 487    *   nor need they even share compatible exception conventions, | 487    *   nor need they even share compatible exception conventions, | 
| 488    *   and might not even be in the same thread. | 488    *   and might not even be in the same thread. | 
| 489    * Thus, if the applied function throws an exception, | 489    * Thus, if the applied function throws an exception, | 
| 490    *   we catch it in the callback and re-throw it in the enumerator. | 490    *   we catch it in the callback and re-throw it in the enumerator. | 
| 491    * This member holds such an exception. | 491    * This member holds such an exception. | 
| 492    * | 492    * | 
| 493    * This member holds an exception only if 'status' has the value 'exception'. | 493    * This member holds an exception only if 'status' has the value 'exception'. | 
| 494    * Otherwise it's a null pointer. | 494    * Otherwise it's a null pointer. | 
| 495    */ | 495    */ | 
| 496   std::unique_ptr< std::exception > ee ; | 496   std::unique_ptr< std::exception > ee ; | 
| 497 | 497 | 
| 498   /** | 498   /** | 
| 499    * Ordinary constructor. | 499    * Ordinary constructor. | 
| 500    */ | 500    */ | 
| 501   ew_data( F & f ) | 501   EWData( F & f ) | 
| 502     : f( f ), status( started ) | 502     : f( f ), status( started ) | 
| 503   {} | 503   {} | 
| 504 } ; | 504 } ; | 
| 505 | 505 | 
| 506 /** | 506 /** | 
| 507  * Callback function for EnumWindows. | 507  * Callback function for EnumWindows. | 
| 508  * | 508  * | 
| 509  * This function provides two standard behaviors. | 509  * This function provides two standard behaviors. | 
| 510  * It records early termination of the enumeration, should that happen by the ap
     plied function returning false. | 510  * It records early termination of the enumeration, should that happen by the ap
     plied function returning false. | 
| 511  * It captures any exception thrown for transport back to the enumerator. | 511  * It captures any exception thrown for transport back to the enumerator. | 
| 512  */ | 512  */ | 
| 513 template< class F > | 513 template< class F > | 
| 514 BOOL CALLBACK enumeration_callback( HWND window, LPARAM x ) | 514 BOOL CALLBACK EnumerationCallback( HWND window, LPARAM x ) | 
| 515 { | 515 { | 
| 516   // LPARAM is always the same size as a pointer | 516   // LPARAM is always the same size as a pointer | 
| 517   ew_data< F > * data = reinterpret_cast< ew_data< F > * >( x ) ; | 517   EWData< F > * data = reinterpret_cast< EWData< F > * >( x ) ; | 
| 518   /* | 518   /* | 
| 519    * Top-level try statement prevents exception from propagating back to system. | 519    * Top-level try statement prevents exception from propagating back to system. | 
| 520    */ | 520    */ | 
| 521   try | 521   try | 
| 522   { | 522   { | 
| 523     bool r = data -> f( window ) ; | 523     bool r = data -> f( window ) ; | 
| 524     if ( ! r ) | 524     if ( ! r ) | 
| 525     { | 525     { | 
| 526       data -> status = early ; | 526       data -> status = early ; | 
| 527     } | 527     } | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
| 538     data -> ee = std::unique_ptr< std::exception >() ; | 538     data -> ee = std::unique_ptr< std::exception >() ; | 
| 539     data -> status = exception ; | 539     data -> status = exception ; | 
| 540     return FALSE ; | 540     return FALSE ; | 
| 541   } | 541   } | 
| 542 } | 542 } | 
| 543 | 543 | 
| 544 /** | 544 /** | 
| 545  * Enumerate windows, applying a function to each one. | 545  * Enumerate windows, applying a function to each one. | 
| 546  */ | 546  */ | 
| 547 template< class F > | 547 template< class F > | 
| 548 bool enumerate_windows( F f ) | 548 bool EnumerateWindows( F f ) | 
| 549 { | 549 { | 
| 550   ew_data< F > data( f ) ; | 550   EWData< F > data( f ) ; | 
| 551   BOOL x( ::EnumWindows( enumeration_callback< F >, reinterpret_cast< LPARAM >( 
     & data ) ) ) ; | 551   BOOL x( ::EnumWindows( EnumerationCallback< F >, reinterpret_cast< LPARAM >( &
      data ) ) ) ; | 
| 552   bool r ; | 552   bool r ; | 
| 553   if ( data.status != started ) | 553   if ( data.status != started ) | 
| 554   { | 554   { | 
| 555     // Assert status was changed within the callback | 555     // Assert status was changed within the callback | 
| 556     if ( data.status == exception ) | 556     if ( data.status == exception ) | 
| 557     { | 557     { | 
| 558       /* | 558       /* | 
| 559        * The callback threw an exception of some sort. | 559        * The callback threw an exception of some sort. | 
| 560        * We forward it to the extent we are able. | 560        * We forward it to the extent we are able. | 
| 561        */ | 561        */ | 
| (...skipping 26 matching lines...) Expand all  Loading... | 
| 588 } | 588 } | 
| 589 | 589 | 
| 590 //------------------------------------------------------- | 590 //------------------------------------------------------- | 
| 591 // ProcessCloser | 591 // ProcessCloser | 
| 592 //------------------------------------------------------- | 592 //------------------------------------------------------- | 
| 593 class ProcessCloser | 593 class ProcessCloser | 
| 594 { | 594 { | 
| 595   /** | 595   /** | 
| 596    * Set of process identifiers matching one of the executable names. | 596    * Set of process identifiers matching one of the executable names. | 
| 597    */ | 597    */ | 
| 598   std::set< DWORD > pid_set ; | 598   std::set< DWORD > pidSet ; | 
| 599 | 599 | 
| 600   /** | 600   /** | 
| 601    * Set of executable names by which to filter. | 601    * Set of executable names by which to filter. | 
| 602    * | 602    * | 
| 603    * The argument of the filter constructor is a set by reference. | 603    * The argument of the filter constructor is a set by reference. | 
| 604    * Since it does not make a copy for itself, we define it as a class member to
      provide its allocation. | 604    * Since it does not make a copy for itself, we define it as a class member to
      provide its allocation. | 
| 605    */ | 605    */ | 
| 606   file_name_set process_names ; | 606   FileNameSet processNames ; | 
| 607 | 607 | 
| 608   process_by_any_exe_not_immersive filter ; | 608   ProcessByAnyExeNotImmersive filter ; | 
| 609 | 609 | 
| 610   /** | 610   /** | 
| 611    * Copy function object copies just the process ID. | 611    * Copy function object copies just the process ID. | 
| 612    */ | 612    */ | 
| 613   copy_PID copy ; | 613   CopyPID copy ; | 
| 614 | 614 | 
| 615   /** | 615   /** | 
| 616    * Snapshot of running processes. | 616    * Snapshot of running processes. | 
| 617    */ | 617    */ | 
| 618   ProcessSnapshot & snapshot ; | 618   ProcessSnapshot & snapshot ; | 
| 619 | 619 | 
| 620   void update() | 620   void update() | 
| 621   { | 621   { | 
| 622     initialize_process_set( pid_set, snapshot, filter, copy ) ; | 622     InitializeProcessSet( pidSet, snapshot, filter, copy ) ; | 
| 623   } ; | 623   } ; | 
| 624 | 624 | 
| 625   template< class F > | 625   template< class F > | 
| 626   class only_our_processes | 626   class OnlyOurProcesses | 
| 627   { | 627   { | 
| 628     ProcessCloser & self ; | 628     ProcessCloser & self ; | 
| 629 | 629 | 
| 630     F f ; | 630     F f ; | 
| 631 | 631 | 
| 632   public: | 632   public: | 
| 633     only_our_processes( ProcessCloser & self, F f ) | 633     OnlyOurProcesses( ProcessCloser & self, F f ) | 
| 634       : f( f ), self( self ) | 634       : f( f ), self( self ) | 
| 635     {} | 635     {} | 
| 636 | 636 | 
| 637     bool operator()( HWND window ) | 637     bool operator()( HWND window ) | 
| 638     { | 638     { | 
| 639       bool b ; | 639       bool b ; | 
| 640       try | 640       try | 
| 641       { | 641       { | 
| 642 »       b = self.contains( creator_process( window ) ) ; | 642         b = self.Contains( CreatorProcess( window ) ) ; | 
| 643       } | 643       } | 
| 644       catch ( ... ) | 644       catch ( ... ) | 
| 645       { | 645       { | 
| 646 »       // ignore window handles that are no longer valid | 646         // ignore window handles that are no longer valid | 
| 647 »       return true ; | 647         return true ; | 
| 648       } | 648       } | 
| 649       if ( ! b ) | 649       if ( ! b ) | 
| 650       { | 650       { | 
| 651 »       // Assert the process that created the window is not in our pid_set | 651         // Assert the process that created the window is not in our pidSet | 
| 652 »       return true ; | 652         return true ; | 
| 653       } | 653       } | 
| 654       return f( window ) ; | 654       return f( window ) ; | 
| 655     } | 655     } | 
| 656   } ; | 656   } ; | 
| 657 | 657 | 
| 658 public: | 658 public: | 
| 659   template <size_t n_file_names> | 659   template <size_t nFileNames> | 
| 660   ProcessCloser(ProcessSnapshot & snapshot, const wchar_t * (&file_name_list)[n_
     file_names]) | 660   ProcessCloser(ProcessSnapshot & snapshot, const wchar_t * (&fileNameList)[nFil
     eNames]) | 
| 661     : snapshot(snapshot), process_names(file_name_list), filter(process_names) | 661     : snapshot(snapshot), processNames(fileNameList), filter(processNames) | 
| 662   { | 662   { | 
| 663     update() ; | 663     update() ; | 
| 664   } | 664   } | 
| 665 | 665 | 
| 666   /** | 666   /** | 
| 667    * Refresh our state to match the snapshot state. | 667    * Refresh our state to match the snapshot state. | 
| 668    */ | 668    */ | 
| 669   void Refresh() | 669   void Refresh() | 
| 670   { | 670   { | 
| 671     pid_set.clear() ; | 671     pidSet.clear() ; | 
| 672     update() ; | 672     update() ; | 
| 673   } | 673   } | 
| 674 | 674 | 
| 675   bool IsRunning() { return ! pid_set.empty() ; } ; | 675   bool IsRunning() { return ! pidSet.empty() ; } ; | 
| 676 | 676 | 
| 677   bool contains( DWORD pid ) const { return pid_set.find( pid ) != pid_set.end()
      ; } ; | 677   bool Contains( DWORD pid ) const { return pidSet.find( pid ) != pidSet.end() ;
      } ; | 
| 678 | 678 | 
| 679   template< class F > | 679   template< class F > | 
| 680   bool iterate_our_windows( F f ) | 680   bool IterateOurWindows( F f ) | 
| 681   { | 681   { | 
| 682     only_our_processes< F > g( * this, f ) ; | 682     OnlyOurProcesses< F > g( * this, f ) ; | 
| 683     return enumerate_windows( g ) ; | 683     return EnumerateWindows( g ) ; | 
| 684   } | 684   } | 
| 685 | 685 | 
| 686   /* | 686   /* | 
| 687    * Shut down every process in the pid_set. | 687    * Shut down every process in the pidSet. | 
| 688    */ | 688    */ | 
| 689   bool ShutDown() ; | 689   bool ShutDown() ; | 
| 690 | 690 | 
| 691 } ; | 691 } ; | 
| 692 | 692 | 
| 693 #endif | 693 #endif | 
| OLD | NEW | 
|---|