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 |