| 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 ) ; |
| } |
| } |