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