| Index: installer/src/installer-lib/process.h | 
| =================================================================== | 
| --- a/installer/src/installer-lib/process.h | 
| +++ b/installer/src/installer-lib/process.h | 
| @@ -5,6 +5,7 @@ | 
| #ifndef PROCESS_H | 
| #define PROCESS_H | 
|  | 
| +#include "installer-lib.h" | 
| #include "handle.h" | 
|  | 
| #include <string> | 
| @@ -63,7 +64,6 @@ | 
|  | 
| typedef std::basic_string< wchar_t, ci_traits< wchar_t > > wstring_ci ; | 
|  | 
| - | 
| //------------------------------------------------------- | 
| // file_name_set: case-insensitive wide-string set | 
| //------------------------------------------------------- | 
| @@ -167,7 +167,71 @@ | 
| // Snapshot | 
| //------------------------------------------------------- | 
| /** | 
| - * A snapshot of all the processes running on the system. | 
| + * Traits class for snapshots of all processes on the system. | 
| + */ | 
| +struct Process_Snapshot_Traits | 
| +{ | 
| +  /** | 
| +   * The type of the data resulting from CreateToolhelp32Snapshot. | 
| +   */ | 
| +  typedef PROCESSENTRY32W result_type ; | 
| + | 
| +  /** | 
| +   * Flags used to call CreateToolhelp32Snapshot. | 
| +   */ | 
| +  const static DWORD snapshot_flags = TH32CS_SNAPPROCESS ; | 
| + | 
| +  /** | 
| +   * Wrapper for 'first' function for processes | 
| +   */ | 
| +  static BOOL first( HANDLE arg1, LPPROCESSENTRY32 arg2 ) | 
| +  { | 
| +    return ::Process32First( arg1, arg2 ) ; | 
| +  } | 
| + | 
| +  /** | 
| +   * Wrapper for 'next' function for processes | 
| +   */ | 
| +  static BOOL next( HANDLE arg1, LPPROCESSENTRY32 arg2 ) | 
| +  { | 
| +    return ::Process32Next( arg1, arg2 ) ; | 
| +  } | 
| +} ; | 
| + | 
| +/** | 
| + * Traits class for snapshots of all modules loaded by a process. | 
| + */ | 
| +struct Module_Snapshot_Traits | 
| +{ | 
| +  /** | 
| +   * The type of the data resulting from CreateToolhelp32Snapshot. | 
| +   */ | 
| +  typedef MODULEENTRY32W result_type ; | 
| + | 
| +  /** | 
| +   * Flags used to call CreateToolhelp32Snapshot. | 
| +   */ | 
| +  const static DWORD snapshot_flags = TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32 ; | 
| + | 
| +  /** | 
| +   * Wrapper for 'first' function for modules | 
| +   */ | 
| +  static BOOL first( HANDLE arg1, LPMODULEENTRY32 arg2 ) | 
| +  { | 
| +    return ::Module32First( arg1, arg2 ) ; | 
| +  } | 
| + | 
| +  /** | 
| +   * Wrapper for 'next' function for modules | 
| +   */ | 
| +  static BOOL next( HANDLE arg1, LPMODULEENTRY32 arg2 ) | 
| +  { | 
| +    return ::Module32Next( arg1, arg2 ) ; | 
| +  } | 
| +} ; | 
| + | 
| +/** | 
| + * A snapshot wrapping the results of CreateToolhelp32Snapshot system call. | 
| * | 
| * Unfortunately, we cannot provide standard iterator for this class. | 
| * Standard iterators must be copy-constructible, which entails the possibility of multiple, coexisting iteration states. | 
| @@ -175,9 +239,7 @@ | 
| * Thus, there can be only one iterator at a time for the snapshot. | 
| * The two requirements are not simultaneously satisfiable. | 
| * | 
| - * As a substitute for a standard iterator, we provide a few functions mimicking the pattern of standard iterators. | 
| - * This class acts as its own iterator. | 
| - * The pointer returned is either one to the member variable "process" or else 0. | 
| + * Instead of a standard iterator, we provide a first() and next() functions wrapping the corresponding system calls. | 
| * | 
| * \par Implementation | 
| * | 
| @@ -185,18 +247,41 @@ | 
| * - MSDN [Process32First function](http://msdn.microsoft.com/en-us/library/windows/desktop/ms684834%28v=vs.85%29.aspx) | 
| * - MSDN [Process32Next function](http://msdn.microsoft.com/en-us/library/windows/desktop/ms684836%28v=vs.85%29.aspx) | 
| * - MSDN [PROCESSENTRY32 structure](http://msdn.microsoft.com/en-us/library/windows/desktop/ms684839%28v=vs.85%29.aspx) | 
| + * | 
| + * \par Design Note | 
| + *   The traits class defines first() and next() functions instead of using function pointers. | 
| + *   This arises from a limitation in the compiler. | 
| + *   The system calls are declared 'WINAPI', which is a compiler-specific extension. | 
| + *   That extension, however, does not go far enough to be able to declare a pointer with the same modifier. | 
| + *   Hence the system calls must be called directly; they are wrapped in the trait functions. | 
| */ | 
| +template< class Traits > | 
| class Snapshot | 
| { | 
| +public: | 
| /** | 
| -   * Handle to the process snapshot. | 
| +   * Expose the result type from the traits class as our own. | 
| +   */ | 
| +  typedef typename Traits::result_type result_type ; | 
| + | 
| +private: | 
| +  /** | 
| +   * Process ID argument for CreateToolhelp32Snapshot. | 
| +   */ | 
| +  DWORD _id ; | 
| + | 
| +  /** | 
| +   * Handle to the underlying snapshot. | 
| */ | 
| Windows_Handle handle ; | 
|  | 
| /** | 
| * Buffer for reading a single process entry out of the snapshot. | 
| +   * | 
| +   * This buffer is constant insofar as the code outside this class is concerned. | 
| +   * The accessor functions first() and next() return pointers to constant result_type. | 
| */ | 
| -  PROCESSENTRY32W process; | 
| +  result_type buffer; | 
|  | 
| /** | 
| * Copy constructor declared private and not defined. | 
| @@ -214,77 +299,101 @@ | 
| */ | 
| Snapshot operator=( const Snapshot & ) ; | 
|  | 
| +  /** | 
| +   * Create a new snapshot and return its handle. | 
| +   */ | 
| +  Windows_Handle::handle_type make_handle() | 
| +  { | 
| +    Windows_Handle::handle_type h = ::CreateToolhelp32Snapshot( Traits::snapshot_flags, _id ) ; | 
| +    if ( h == INVALID_HANDLE_VALUE ) | 
| +    { | 
| +      throw windows_api_error( "CreateToolhelp32Snapshot", "INVALID_HANDLE_VALUE" ) ; | 
| +    } | 
| +    return h ; | 
| +  } | 
| + | 
| +protected: | 
| +  /** | 
| +   * Constructor takes a snapshot. | 
| +   */ | 
| +  Snapshot( DWORD id ) | 
| +    : _id( id ), handle( make_handle() ) | 
| +  { | 
| +    // The various result types all define 'dwSize' with the same semantics. | 
| +    buffer.dwSize = sizeof( result_type ) ; | 
| +  } | 
|  | 
| public: | 
| /** | 
| -   * Default constructor takes the snapshot. | 
| +   * Reconstruct the current instance with a new system snapshot. | 
| +   * | 
| +   * This function uses reinitialization assignment in the Windows_Handle class, | 
| +   *   which takes care of closing the old handle. | 
| */ | 
| -  Snapshot() ; | 
| +  void refresh() | 
| +  { | 
| +    handle = make_handle(); | 
| +  } | 
|  | 
| /** | 
| -   * Reconstruct the current instance with a new system snapshot. | 
| +   * Retrieve the first snapshot item into our member buffer. | 
| +   * | 
| +   * \return | 
| +   *   Pointer to our member buffer if there was a first item | 
| +   *   0 otherwise | 
| +   * | 
| +   * \par Design Note | 
| +   *   There's no error handling in the present version of this function. | 
| +   *   In part that's because the underlying system call returns either true or false, both of which are ordinarily valid answers. | 
| +   *   The trouble is that a false return is overloaded. | 
| +   *   It can mean either that (ordinary) there are no more items or (exceptional) the snapshot did not contain the right kind of item. | 
| +   *   GetLastError is no help here; it doesn't distinguish between these cases. | 
| +   *   The upshot is that we rely that our implementation calls the right functions on the snapshot, | 
| +   *     and so we ignore the case where we've passed bad arguments to the system call. | 
| */ | 
| -  void refresh() ; | 
| +  const result_type * first() | 
| +  { | 
| +    return Traits::first(handle, &buffer) ? &buffer : 0; | 
| +  } | 
|  | 
| /** | 
| -   * Return a pointer to the first process in the snapshot. | 
| +   * Retrieve the next snapshot item into our member buffer and return a pointer to it. | 
| +   * begin() must have been called first. | 
| +   * | 
| +   * \return | 
| +   *   Pointer to our member buffer if there was a first item | 
| +   *   0 otherwise | 
| +   * | 
| +   * \par Design Note | 
| +   *   See the Design Note for first(); the same considerations apply here. | 
| */ | 
| -  PROCESSENTRY32W * first() ; | 
| - | 
| -  /** | 
| -   * Return a pointer to the next process in the snapshot. | 
| -   * begin() must have been called first. | 
| -   */ | 
| -  PROCESSENTRY32W * next() ; | 
| +  const result_type * next() | 
| +  { | 
| +    return Traits::next(handle, &buffer) ? &buffer : 0; | 
| +  } | 
| } ; | 
|  | 
| -class ModulesSnapshot | 
| +/** | 
| + * A snapshot of all processes running on the system. | 
| + */ | 
| +struct Process_Snapshot | 
| +  : public Snapshot< Process_Snapshot_Traits > | 
| { | 
| -  /** | 
| -   * Handle to the process snapshot. | 
| -   */ | 
| -  Windows_Handle handle; | 
| +  Process_Snapshot() | 
| +    : Snapshot( 0 ) | 
| +  {} | 
| +} ; | 
|  | 
| -  /** | 
| -   * Buffer for reading a single module entry out of the snapshot. | 
| -   */ | 
| -  MODULEENTRY32W module; | 
| - | 
| -  /** | 
| -   * Copy constructor declared private and not defined. | 
| -   * | 
| -   * \par Implementation | 
| -   *   Add "= delete" for C++11. | 
| -   */ | 
| -  ModulesSnapshot(const ModulesSnapshot&); | 
| - | 
| -  /** | 
| -   * Copy assignment declared private and not defined. | 
| -   * | 
| -   * \par Implementation | 
| -   *   Add "= delete" for C++11. | 
| -   */ | 
| -  ModulesSnapshot operator=(const ModulesSnapshot&); | 
| - | 
| - | 
| -public: | 
| -  /** | 
| -   * Default constructor takes the snapshot. | 
| -   */ | 
| -  ModulesSnapshot(DWORD processId); | 
| - | 
| -  /** | 
| -   * Return a pointer to the first process in the snapshot. | 
| -   */ | 
| -  MODULEENTRY32W* first(); | 
| - | 
| -  /** | 
| -   * Return a pointer to the next process in the snapshot. | 
| -   * begin() must have been called first. | 
| -   */ | 
| -  MODULEENTRY32W* next(); | 
| -}; | 
| - | 
| +/** | 
| + * A snapshot of all modules loaded for a given process. | 
| + */ | 
| +struct Module_Snapshot | 
| +  : public Snapshot< Module_Snapshot_Traits > | 
| +{ | 
| +  Module_Snapshot( DWORD process_id ) | 
| +    : Snapshot( process_id ) | 
| +  {} | 
| +} ; | 
|  | 
| //------------------------------------------------------- | 
| // initialize_process_list | 
| @@ -299,10 +408,10 @@ | 
| * \param convert A conversion function that takes a PROCESSENTRY32W as input argument and returns an element of type T. | 
| */ | 
| template<class T, class Admittance, class Extractor> | 
| -void initialize_process_list(std::vector<T>& v, Snapshot& snap, Admittance admit = Admittance(), Extractor extract = Extractor()) | 
| +void initialize_process_list(std::vector<T>& v, Process_Snapshot &snap, Admittance admit = Admittance(), Extractor extract = Extractor()) | 
| { | 
| -  PROCESSENTRY32W* p = snap.first(); | 
| -  while (p != NULL) | 
| +  const PROCESSENTRY32W* p = snap.first(); | 
| +  while (p != 0) | 
| { | 
| if (admit(*p )) | 
| { | 
| @@ -329,10 +438,10 @@ | 
| * \param convert A conversion function that takes a PROCESSENTRY32W as input argument and returns an element of type T. | 
| */ | 
| template<class T, class Admittance, class Extractor> | 
| -void initialize_process_set(std::set< T > & set, Snapshot& snap, Admittance admit = Admittance(), Extractor extract = Extractor()) | 
| +void initialize_process_set(std::set< T > & set, Process_Snapshot &snap, Admittance admit = Admittance(), Extractor extract = Extractor()) | 
| { | 
| -  PROCESSENTRY32W* p = snap.first(); | 
| -  while (p != NULL) | 
| +  const PROCESSENTRY32W* p = snap.first(); | 
| +  while (p != 0) | 
| { | 
| if (admit(*p)) | 
| { | 
| @@ -514,7 +623,7 @@ | 
| /** | 
| * Snapshot of running processes. | 
| */ | 
| -  Snapshot & snapshot ; | 
| +  Process_Snapshot & snapshot ; | 
|  | 
| void update() | 
| { | 
| @@ -556,13 +665,13 @@ | 
|  | 
| public: | 
| template <size_t n_file_names, size_t n_module_names> | 
| -  Process_Closer(Snapshot & snapshot, const wchar_t* (&file_name_list)[n_file_names], const wchar_t* (&module_name_list)[n_module_names]) | 
| +  Process_Closer(Process_Snapshot & snapshot, const wchar_t* (&file_name_list)[n_file_names], const wchar_t* (&module_name_list)[n_module_names]) | 
| : snapshot(snapshot), process_names(file_name_list), module_names(module_name_list), filter(process_names, module_names) | 
| { | 
| update() ; | 
| } | 
| template <size_t n_file_names> | 
| -  Process_Closer(Snapshot & snapshot, const wchar_t * (&file_name_list)[n_file_names]) | 
| +  Process_Closer(Process_Snapshot & snapshot, const wchar_t * (&file_name_list)[n_file_names]) | 
| : snapshot(snapshot), process_names(file_name_list), module_names(), filter(process_names, module_names) | 
| { | 
| update() ; | 
|  |