| Index: installer/src/installer-lib/property.cpp |
| =================================================================== |
| new file mode 100644 |
| --- /dev/null |
| +++ b/installer/src/installer-lib/property.cpp |
| @@ -0,0 +1,67 @@ |
| +/** |
| + * \file property.cpp Implementation of Property class etc. |
| + */ |
| + |
| +#include "property.h" |
| +#include "session.h" |
| +#include "msiquery.h" |
| +#include <memory> |
| + |
| +//----------------------------------------------------------------------------------------- |
| +// Property |
| +//----------------------------------------------------------------------------------------- |
| +Property::Property( Session & session, std::wstring name ) |
| + // VSE 2012 shows an IntelliSense error here. Ignore it. The compiler properly sees the 'friend' declaration. |
| + : handle( session.handle ), name( name ) |
| +{} |
| + |
| +/** |
| + * \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 |
| + */ |
|
Wladimir Palant
2013/10/29 08:49:26
The logic is actually common for any API that does
Eric
2013/10/29 14:00:58
I'll rewrite the comment. Reading it again, it doe
|
| + // 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 ) ; |
|
Wladimir Palant
2013/10/29 08:49:26
sizeof(TCHAR) => sizeof(buffer1[0])?
Eric
2013/10/29 14:00:58
TCHAR is, as I recall, a wchar_t for Unicode compi
Wladimir Palant
2013/10/29 15:06:38
What I meant: you can replace sizeof(TCHAR) by siz
|
| + switch ( MsiGetProperty( handle, name.c_str(), buffer1, & length ) ) |
| + { |
| + case ERROR_SUCCESS: |
| + // This call might succeed, which means the return value was short enough to fit into the buffer. |
| + return std::wstring( buffer1, length ) ; |
| + case ERROR_MORE_DATA: |
| + // Do nothing yet. |
| + break ; |
| + default: |
| + throw std::runtime_error( "Error getting property" ) ; |
| + } |
| + // 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 ) ) |
| + { |
| + case ERROR_SUCCESS: |
| + return std::wstring( buffer2.get(), length ) ; |
| + default: |
| + throw std::runtime_error( "Error getting property" ) ; |
| + } |
|
Wladimir Palant
2013/10/29 08:49:26
Any reason why this isn't an if..else.. block? Als
Eric
2013/10/29 14:00:58
There are three other error codes defined for the
|
| +} |
| + |
| +/** |
| + * \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 ) |
| + { |
| + throw std::runtime_error( "Error setting property" ) ; |
|
Wladimir Palant
2013/10/29 08:49:26
This exception isn't very helpful, it should conta
Eric
2013/10/29 14:00:58
Admittedly, the exceptions here are stubs. I don't
Wladimir Palant
2013/10/29 15:06:38
Forgot to mention that: where are these exceptions
Eric
2014/03/28 13:56:38
The answer is a general one.
Every time you use
|
| + } |
| +} |