| Index: installer/src/installer-lib/session.cpp | 
| =================================================================== | 
| --- a/installer/src/installer-lib/session.cpp | 
| +++ b/installer/src/installer-lib/session.cpp | 
| @@ -1,53 +1,96 @@ | 
| /** | 
| - * \file session.cpp Implementation of Session class. | 
| - */ | 
| +* \file session.cpp Implementation of Session class. | 
| +*/ | 
|  | 
| +#include "installer-lib.h" | 
| #include "session.h" | 
| #include "property.h" | 
| #include "msiquery.h" | 
|  | 
| //----------------------------------------------------------------------------------------- | 
| +// Message | 
| +//----------------------------------------------------------------------------------------- | 
| +Message::Message( std::string message, INSTALLMESSAGE message_type ) | 
| +  : r( 1 ), message_type( message_type ) | 
| +{ | 
| +  r.assign_string( 0, message ) ; | 
| +} | 
| + | 
| +Message::Message( std::wstring message, INSTALLMESSAGE message_type ) | 
| +  : r( 1 ), message_type( message_type ) | 
| +{ | 
| +  r.assign_string( 0, message ) ; | 
| +} | 
| + | 
| +//----------------------------------------------------------------------------------------- | 
| // Session | 
| //----------------------------------------------------------------------------------------- | 
| -Session::Session( MSIHANDLE handle, std::wstring name ) | 
| +Session::Session( MSIHANDLE handle, std::string name ) | 
| : handle( handle ), | 
| -  log_prefix( name + L": " ) | 
| +  log_prefix( name + ": " ) | 
| { | 
| -  log( L"Entering custom action" ) ; | 
| +  log_prefix_w.assign( name.begin(), name.end() ) ; | 
| +  log_prefix_w += L": " ; | 
| +  log_noexcept( "Entering custom action" ) ; | 
| +} | 
| + | 
| +Session::~Session() | 
| +{ | 
| +  log_noexcept( "Exiting custom action" ) ; | 
| } | 
|  | 
| /** | 
| - * \par Implementation Notes | 
| - *    The session handle doesn't need to be closed. | 
| - *    It's provided as an argument to the custom action at the outset, and we do not manage its life cycle. | 
| - */ | 
| -Session::~Session() | 
| +* A message for the installation log. | 
| +* | 
| +* Writing to the installation log uses MsiProcessMessage just like interactive dialog boxes do. | 
| +* | 
| +* This class is not exposed outside this compilation unit because everything it can do is already exposed by the log functions. | 
| +*/ | 
| +struct Log_Message | 
| +  : public Message | 
| { | 
| -  log( L"Exiting custom action" ) ; | 
| +  Log_Message ( std::wstring message ) | 
| +    : Message( message, INSTALLMESSAGE_INFO ) | 
| +  {} | 
| + | 
| +  Log_Message ( std::string message ) | 
| +    : Message( message, INSTALLMESSAGE_INFO ) | 
| +  {} | 
| +} ; | 
| + | 
| +void Session::log( std::string message ) | 
| +{ | 
| +  write_message( Log_Message( log_prefix + message ) ) ; | 
| } | 
|  | 
| -/** | 
| - * \par Implementation Notes | 
| - *    To write to the installation log, we use a call to MsiProcessMessage with message type INSTALLMESSAGE_INFO. | 
| - *    The text to be written needs to go in a "record" (yes, a database record) that acts as an argument vector. | 
| - *    For the message type we're using, we need only a record with a single field. | 
| - * | 
| - * \sa MSDN "MsiProcessMessage function" | 
| - *    http://msdn.microsoft.com/en-us/library/windows/desktop/aa370354%28v=vs.85%29.aspx | 
| - *    MsiProcessMessage is mostly for user interaction with message boxes, but it's also the access to the installation log. | 
| - */ | 
| void Session::log( std::wstring message ) | 
| { | 
| -  Record r = Record( 1 ); | 
| -  r.assign_string( 0, log_prefix + message ); | 
| -  int e = MsiProcessMessage( handle, INSTALLMESSAGE_INFO, r.handle() ) ; | 
| -  if ( e != IDOK ) | 
| -  { | 
| -    throw std::runtime_error( "Did not succeed writing to log." ) ; | 
| -  } | 
| +  write_message( Log_Message( log_prefix_w + message ) ) ; | 
| } | 
|  | 
| -Immediate_Session::Immediate_Session( MSIHANDLE handle, std::wstring name ) | 
| +void Session::log_noexcept( std::string message ) | 
| +{ | 
| +  write_message_noexcept( Log_Message( log_prefix + message ) ) ; | 
| +} | 
| + | 
| +int Session::write_message( Message & m ) | 
| +{ | 
| +  int x = write_message_noexcept( m ) ; | 
| +  if ( x == -1 ) | 
| +  { | 
| +    throw windows_api_error( "MsiProcessMessage", x, "attempt to write to log file" ) ; | 
| +  } | 
| +  return x ; | 
| +} | 
| + | 
| +int Session::write_message_noexcept( Message & m ) | 
| +{ | 
| +  return MsiProcessMessage( handle, m.message_type, m.r.handle() ) ; | 
| +} | 
| + | 
| +//----------------------------------------------------------------------------------------- | 
| +// Immediate_Session | 
| +//----------------------------------------------------------------------------------------- | 
| +Immediate_Session::Immediate_Session( MSIHANDLE handle, std::string name ) | 
| : Session( handle, name ) | 
| -{ | 
| -} | 
| +{} | 
|  |