| OLD | NEW | 
|---|
| 1 /** | 1 /** | 
| 2 * \file handle.h The "install session" is the context for all custom installatio
     n behavior. | 2 * \file handle.h The "install session" is the context for all custom installatio
     n behavior. | 
| 3 */ | 3 */ | 
| 4 | 4 | 
| 5 #ifndef INSTALLER_LIB_H | 5 #ifndef INSTALLER_LIB_H | 
| 6 #define INSTALLER_LIB_H | 6 #define INSTALLER_LIB_H | 
| 7 | 7 | 
| 8 #include <stdexcept> | 8 #include <stdexcept> | 
| 9 #include <sstream> | 9 #include <sstream> | 
| 10 | 10 | 
| 11 /** | 11 /** | 
| 12 * Standard runtime error for failure of Windows API calls. | 12 * Standard runtime error for failure of Windows API calls. | 
| 13 * | 13 * | 
| 14 * The design purpose of this class is to consistently report the details of a fa
     iled API call, with an eye toward logging. | 14 * The design purpose of this class is to consistently report the details of a fa
     iled API call, with an eye toward logging. | 
| 15 * All the arguments passed to the constructor appear in what(). | 15 * All the arguments passed to the constructor appear in what(). | 
| 16 * In addition the return value of GetLastError() appears. | 16 * In addition the return value of GetLastError() appears. | 
| 17 * | 17 * | 
| 18 * All the types for the constructors are generic. | 18 * All the types for the constructors are generic. | 
| 19 * Any type that works with the output operator '<<' of a stream will work. | 19 * Any type that works with the output operator '<<' of a stream will work. | 
| 20 * | 20 * | 
| 21 * \par Example | 21 * \par Example | 
| 22 *   For a simple error, where there's not much to add over the API call and the 
     error code itself, just omit the second argument. | 22 *   For a simple error, where there's not much to add over the API call and the 
     error code itself, just omit the second argument. | 
| 23 *   \code | 23 *   \code | 
| 24 *     throw windows_api_error( "MsiDatabaseOpenView", "ERROR_BAD_QUERY_SYNTAX" ) | 24 *     throw WindowsApiError( "MsiDatabaseOpenView", "ERROR_BAD_QUERY_SYNTAX" ) | 
| 25 *   \endcode | 25 *   \endcode | 
| 26 * | 26 * | 
| 27 * \par | 27 * \par | 
| 28 *   Sometimes you don't have a symbolic error code. | 28 *   Sometimes you don't have a symbolic error code. | 
| 29 *   This example uses a numeric error and a clarifying message. | 29 *   This example uses a numeric error and a clarifying message. | 
| 30 *   \code | 30 *   \code | 
| 31 *     throw windows_api_error( "MsiOpenDatabaseW", x, "MSI database is on file s
     ystem" ) | 31 *     throw WindowsApiError( "MsiOpenDatabaseW", x, "MSI database is on file sys
     tem" ) | 
| 32 *   \endcode | 32 *   \endcode | 
| 33 */ | 33 */ | 
| 34 class windows_api_error | 34 class WindowsApiError | 
| 35   : public std::runtime_error | 35   : public std::runtime_error | 
| 36 { | 36 { | 
| 37   template< class T1, class T2, class T3 > | 37   template< class T1, class T2, class T3 > | 
| 38   static std::string make_message( T1 api_function, T2 error_code, T3 message ) | 38   static std::string MakeMessage( T1 apiFunction, T2 errorCode, T3 message ) | 
| 39   { | 39   { | 
| 40     std::ostringstream r, t ; | 40     std::ostringstream r, t ; | 
| 41     std::string s ; | 41     std::string s ; | 
| 42 | 42 | 
| 43     t << api_function ; | 43     t << apiFunction ; | 
| 44     s = t.str() ; | 44     s = t.str() ; | 
| 45     if ( s.empty() ) | 45     if ( s.empty() ) | 
| 46     { | 46     { | 
| 47       s = "<unspecified>" ; | 47       s = "<unspecified>" ; | 
| 48     } | 48     } | 
| 49     r << s <<  " returned " ; | 49     r << s <<  " returned " ; | 
| 50 | 50 | 
| 51     t = std::ostringstream() ; | 51     t = std::ostringstream() ; | 
| 52     t << error_code ; | 52     t << errorCode ; | 
| 53     s = t.str() ; | 53     s = t.str() ; | 
| 54     if ( s.empty() ) | 54     if ( s.empty() ) | 
| 55     { | 55     { | 
| 56       s = "<unknown>" ; | 56       s = "<unknown>" ; | 
| 57     } | 57     } | 
| 58     r << s << " with last error code " << ::GetLastError() ; | 58     r << s << " with last error code " << ::GetLastError() ; | 
| 59 | 59 | 
| 60     t = std::ostringstream() ; | 60     t = std::ostringstream() ; | 
| 61     t << message ; | 61     t << message ; | 
| 62     s = t.str() ; | 62     s = t.str() ; | 
| 63     if ( ! s.empty() ) | 63     if ( ! s.empty() ) | 
| 64     { | 64     { | 
| 65       r << ": " << s ; | 65       r << ": " << s ; | 
| 66     } | 66     } | 
| 67 | 67 | 
| 68     return r.str() ; | 68     return r.str() ; | 
| 69   } | 69   } | 
| 70 | 70 | 
| 71 public: | 71 public: | 
| 72   /** | 72   /** | 
| 73   * Constructor with additional message. | 73   * Constructor with additional message. | 
| 74   * | 74   * | 
| 75   * \param api_function | 75   * \param apiFunction | 
| 76   *     The name of the API function that returned an error code or a null handl
     e. | 76   *     The name of the API function that returned an error code or a null handl
     e. | 
| 77   * \param error_code | 77   * \param errorCode | 
| 78   *    The error code that the function returned, either symbolic or numeric. | 78   *    The error code that the function returned, either symbolic or numeric. | 
| 79   *    Will be zero when the function returned a null handle. | 79   *    Will be zero when the function returned a null handle. | 
| 80   * \param message | 80   * \param message | 
| 81   *    Extra message to clarify the error | 81   *    Extra message to clarify the error | 
| 82   */ | 82   */ | 
| 83   template< class T1, class T2, class T3 > | 83   template< class T1, class T2, class T3 > | 
| 84   windows_api_error( T1 api_function, T2 error_code, T3 message  ) | 84   WindowsApiError( T1 apiFunction, T2 errorCode, T3 message  ) | 
| 85     : std::runtime_error( make_message( api_function, error_code, message ) ) | 85     : std::runtime_error( MakeMessage( apiFunction, errorCode, message ) ) | 
| 86   {} | 86   {} | 
| 87 | 87 | 
| 88   /** | 88   /** | 
| 89   * Constructor without anything extra. | 89   * Constructor without anything extra. | 
| 90   * | 90   * | 
| 91   * \param api_function | 91   * \param apiFunction | 
| 92   *     The name of the API function that returned an error code or a null handl
     e. | 92   *     The name of the API function that returned an error code or a null handl
     e. | 
| 93   * \param error_code | 93   * \param errorCode | 
| 94   *    The error code that the function returned, either symbolic or numeric. | 94   *    The error code that the function returned, either symbolic or numeric. | 
| 95   *    Will be zero when the function returned a null handle. | 95   *    Will be zero when the function returned a null handle. | 
| 96   */ | 96   */ | 
| 97   template< class T1, class T2 > | 97   template< class T1, class T2 > | 
| 98   windows_api_error( T1 api_function, T2 error_code ) | 98   WindowsApiError( T1 apiFunction, T2 errorCode) | 
| 99     : std::runtime_error( make_message( api_function, error_code, "" ) ) | 99     : std::runtime_error( MakeMessage( apiFunction, errorCode, "" ) ) | 
| 100   {} | 100   {} | 
| 101 } ; | 101 } ; | 
| 102 | 102 | 
| 103 /** | 103 /** | 
| 104 */ | 104 */ | 
| 105 class not_yet_supported | 105 class NotYetSupported | 
| 106   : public std::runtime_error | 106   : public std::runtime_error | 
| 107 { | 107 { | 
| 108 public: | 108 public: | 
| 109   not_yet_supported( std::string message ) | 109   NotYetSupported( std::string message ) | 
| 110     : std::runtime_error( "Not yet supported: " + message ) | 110     : std::runtime_error( "Not yet supported: " + message ) | 
| 111   {} | 111   {} | 
| 112 } ; | 112 } ; | 
| 113 | 113 | 
| 114 #endif | 114 #endif | 
| OLD | NEW | 
|---|