| 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 |