Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: installer/src/installer-lib/property.cpp

Issue 22887001: Custom action library, initial version (Closed)
Patch Set: Created Oct. 28, 2013, 9:37 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
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
+ }
+}

Powered by Google App Engine
This is Rietveld