| Index: installer/src/installer-lib/property.cpp | 
| =================================================================== | 
| --- a/installer/src/installer-lib/property.cpp | 
| +++ b/installer/src/installer-lib/property.cpp | 
| @@ -1,10 +1,11 @@ | 
| /** | 
| - * \file property.cpp Implementation of Property class etc. | 
| - */ | 
| +* \file property.cpp Implementation of Property class etc. | 
| +*/ | 
|  | 
| +#include "installer-lib.h" | 
| #include "property.h" | 
| #include "session.h" | 
| -#include "msiquery.h" | 
| +#include <msiquery.h> | 
| #include <memory> | 
|  | 
| //----------------------------------------------------------------------------------------- | 
| @@ -16,22 +17,21 @@ | 
| {} | 
|  | 
| /** | 
| - * \par Implementation | 
| - * The center of the implementation is the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa370134%28v=vs.85%29.aspx">MsiGetProperty function</a>. | 
| - */ | 
| +* \par Implementation | 
| +* The center of the implementation is the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa370134%28v=vs.85%29.aspx">MsiGetProperty function</a>. | 
| +*/ | 
| Property::operator std::wstring() const | 
| { | 
| /* | 
| -   * The screwy logic below arises from how the API works. | 
| -   * MsiGetProperty insists on copying into your buffer, but you don't know how long that buffer needs to be in advance. | 
| -   * The first call gets the size, but also the actual value if it's short enough. | 
| -   * A second call, if necessary, gets the actual value after allocat | 
| -   */ | 
| -  // We only need a modest fixed-size buffer here, because we handle arbitrary-length property values in a second step. | 
| -  // It has 'auto' allocation, so we don't want it too large. | 
| -  TCHAR buffer1[ 64 ] = { L'\0' } ; | 
| -  DWORD length = sizeof( buffer1 ) / sizeof( TCHAR ) ; | 
| -  switch ( MsiGetProperty( handle, name.c_str(), buffer1, & length ) ) | 
| +  * The first call gets the size, but also the actual value if it's short enough. | 
| +  * A second call, if necessary, allocates a sufficiently-long buffer and then gets the full value. | 
| +  * We use only a modest fixed-size buffer for the first step, because we handle arbitrary-length property values in a second step. | 
| +  */ | 
| +  // This buffer allocates on the stack, so we don't want it too large; 64 characters is enough for most properties anyway. | 
| +  WCHAR buffer1[ 64 ] = { L'\0' } ; | 
| +  DWORD length = sizeof( buffer1 ) / sizeof( WCHAR ) ; | 
| +  UINT x = MsiGetPropertyW( handle, name.c_str(), buffer1, & length ) ; | 
| +  switch ( x ) | 
| { | 
| case ERROR_SUCCESS: | 
| // This call might succeed, which means the return value was short enough to fit into the buffer. | 
| @@ -40,28 +40,30 @@ | 
| // Do nothing yet. | 
| break ; | 
| default: | 
| -    throw std::runtime_error( "Error getting property" ) ; | 
| +    throw windows_api_error( "MsiGetPropertyW", x, "fixed buffer" ) ; | 
| } | 
| // Assert we received ERROR_MORE_DATA | 
| // unique_ptr handles deallocation transparently | 
| -  std::unique_ptr< TCHAR[] > buffer2( new TCHAR[ length ] ); | 
| -  switch ( MsiGetProperty( handle, name.c_str(), buffer2.get(), & length ) ) | 
| +  std::unique_ptr< WCHAR[] > buffer2( new WCHAR[ length ] ) ; | 
| +  x = MsiGetPropertyW( handle, name.c_str(), buffer2.get(), & length ) ; | 
| +  switch ( x ) | 
| { | 
| case ERROR_SUCCESS: | 
| return std::wstring( buffer2.get(), length ) ; | 
| default: | 
| -    throw std::runtime_error( "Error getting property" ) ; | 
| +    throw windows_api_error( "MsiGetPropertyW", x, "allocated buffer" ) ; | 
| } | 
| } | 
|  | 
| /** | 
| - * \par Implementation | 
| - * The center of the implementation is the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa370391%28v=vs.85%29.aspx">MsiSetProperty function</a>. | 
| - */ | 
| +* \par Implementation | 
| +* The center of the implementation is the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa370391%28v=vs.85%29.aspx">MsiSetProperty function</a>. | 
| +*/ | 
| void Property::operator=( const std::wstring & value ) | 
| { | 
| -  if ( MsiSetProperty( handle, name.c_str(), value.c_str() ) != ERROR_SUCCESS ) | 
| +  UINT x = MsiSetPropertyW( handle, name.c_str(), value.c_str() ) ; | 
| +  if ( x != ERROR_SUCCESS ) | 
| { | 
| -    throw std::runtime_error( "Error setting property" ) ; | 
| +    throw windows_api_error( "MsiSetPropertyW", x ) ; | 
| } | 
| } | 
|  |