| OLD | NEW | 
|---|
| 1 /** | 1 /** | 
| 2  * \file property.cpp Implementation of Property class etc. | 2 * \file property.cpp Implementation of Property class etc. | 
| 3  */ | 3 */ | 
| 4 | 4 | 
|  | 5 #include "installer-lib.h" | 
| 5 #include "property.h" | 6 #include "property.h" | 
| 6 #include "session.h" | 7 #include "session.h" | 
| 7 #include "msiquery.h" | 8 #include <msiquery.h> | 
| 8 #include <memory> | 9 #include <memory> | 
| 9 | 10 | 
| 10 //------------------------------------------------------------------------------
    ----------- | 11 //------------------------------------------------------------------------------
    ----------- | 
| 11 // Property | 12 // Property | 
| 12 //------------------------------------------------------------------------------
    ----------- | 13 //------------------------------------------------------------------------------
    ----------- | 
| 13 Property::Property( Session & session, std::wstring name ) | 14 Property::Property( Session & session, std::wstring name ) | 
| 14   // VSE 2012 shows an IntelliSense error here. Ignore it. The compiler properly
     sees the 'friend' declaration. | 15   // VSE 2012 shows an IntelliSense error here. Ignore it. The compiler properly
     sees the 'friend' declaration. | 
| 15   : handle( session.handle ), name( name ) | 16   : handle( session.handle ), name( name ) | 
| 16 {} | 17 {} | 
| 17 | 18 | 
| 18 /** | 19 /** | 
| 19  * \par Implementation | 20 * \par Implementation | 
| 20  * 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>. | 21 * 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>. | 
| 21  */ | 22 */ | 
| 22 Property::operator std::wstring() const | 23 Property::operator std::wstring() const | 
| 23 { | 24 { | 
| 24   /* | 25   /* | 
| 25    * The screwy logic below arises from how the API works. | 26   * The first call gets the size, but also the actual value if it's short enough
    . | 
| 26    * MsiGetProperty insists on copying into your buffer, but you don't know how 
    long that buffer needs to be in advance. | 27   * A second call, if necessary, allocates a sufficiently-long buffer and then g
    ets the full value. | 
| 27    * The first call gets the size, but also the actual value if it's short enoug
    h. | 28   * We use only a modest fixed-size buffer for the first step, because we handle
     arbitrary-length property values in a second step. | 
| 28    * A second call, if necessary, gets the actual value after allocat | 29   */ | 
| 29    */ | 30   // This buffer allocates on the stack, so we don't want it too large; 64 chara
    cters is enough for most properties anyway. | 
| 30   // We only need a modest fixed-size buffer here, because we handle arbitrary-l
    ength property values in a second step. | 31   WCHAR buffer1[ 64 ] = { L'\0' } ; | 
| 31   // It has 'auto' allocation, so we don't want it too large. | 32   DWORD length = sizeof( buffer1 ) / sizeof( WCHAR ) ; | 
| 32   TCHAR buffer1[ 64 ] = { L'\0' } ; | 33   UINT x = MsiGetPropertyW( handle, name.c_str(), buffer1, & length ) ; | 
| 33   DWORD length = sizeof( buffer1 ) / sizeof( TCHAR ) ; | 34   switch ( x ) | 
| 34   switch ( MsiGetProperty( handle, name.c_str(), buffer1, & length ) ) |  | 
| 35   { | 35   { | 
| 36   case ERROR_SUCCESS: | 36   case ERROR_SUCCESS: | 
| 37     // This call might succeed, which means the return value was short enough to
     fit into the buffer. | 37     // This call might succeed, which means the return value was short enough to
     fit into the buffer. | 
| 38     return std::wstring( buffer1, length ) ; | 38     return std::wstring( buffer1, length ) ; | 
| 39   case ERROR_MORE_DATA: | 39   case ERROR_MORE_DATA: | 
| 40     // Do nothing yet. | 40     // Do nothing yet. | 
| 41     break ; | 41     break ; | 
| 42   default: | 42   default: | 
| 43     throw std::runtime_error( "Error getting property" ) ; | 43     throw windows_api_error( "MsiGetPropertyW", x, "fixed buffer" ) ; | 
| 44   } | 44   } | 
| 45   // Assert we received ERROR_MORE_DATA | 45   // Assert we received ERROR_MORE_DATA | 
| 46   // unique_ptr handles deallocation transparently | 46   // unique_ptr handles deallocation transparently | 
| 47   std::unique_ptr< TCHAR[] > buffer2( new TCHAR[ length ] ); | 47   std::unique_ptr< WCHAR[] > buffer2( new WCHAR[ length ] ) ; | 
| 48   switch ( MsiGetProperty( handle, name.c_str(), buffer2.get(), & length ) ) | 48   x = MsiGetPropertyW( handle, name.c_str(), buffer2.get(), & length ) ; | 
|  | 49   switch ( x ) | 
| 49   { | 50   { | 
| 50   case ERROR_SUCCESS: | 51   case ERROR_SUCCESS: | 
| 51     return std::wstring( buffer2.get(), length ) ; | 52     return std::wstring( buffer2.get(), length ) ; | 
| 52   default: | 53   default: | 
| 53     throw std::runtime_error( "Error getting property" ) ; | 54     throw windows_api_error( "MsiGetPropertyW", x, "allocated buffer" ) ; | 
| 54   } | 55   } | 
| 55 } | 56 } | 
| 56 | 57 | 
| 57 /** | 58 /** | 
| 58  * \par Implementation | 59 * \par Implementation | 
| 59  * 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>. | 60 * 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>. | 
| 60  */ | 61 */ | 
| 61 void Property::operator=( const std::wstring & value ) | 62 void Property::operator=( const std::wstring & value ) | 
| 62 { | 63 { | 
| 63   if ( MsiSetProperty( handle, name.c_str(), value.c_str() ) != ERROR_SUCCESS ) | 64   UINT x = MsiSetPropertyW( handle, name.c_str(), value.c_str() ) ; | 
|  | 65   if ( x != ERROR_SUCCESS ) | 
| 64   { | 66   { | 
| 65     throw std::runtime_error( "Error setting property" ) ; | 67     throw windows_api_error( "MsiSetPropertyW", x ) ; | 
| 66   } | 68   } | 
| 67 } | 69 } | 
| OLD | NEW | 
|---|