| Index: installer/src/installer-lib/database.h |
| =================================================================== |
| --- a/installer/src/installer-lib/database.h |
| +++ b/installer/src/installer-lib/database.h |
| @@ -6,11 +6,21 @@ |
| #define DATABASE_H |
| #include <string> |
| -#include "windows.h" |
| -#include "msi.h" |
| +#include <memory> |
| +#include <Windows.h> |
| +#include <Msi.h> |
| +#include <MsiQuery.h> |
| + |
| +#include "handle.h" |
| #include "session.h" |
| +// Forward declarations |
| +class View ; |
| + |
| +//------------------------------------------------------- |
| +// Database |
| +//------------------------------------------------------- |
| /** |
| * A Windows Installer database as contained in an MSI file. |
| * |
| @@ -25,32 +35,50 @@ |
| class Database |
| { |
| protected: |
| - /** |
| - * Protected constructor. Life cycle depends strongly on context. |
| - */ |
| - Database( MSIHANDLE handle ); |
| + typedef handle< MSIHANDLE, Disallow_Null, MSI_Generic_Destruction > handle_type ; |
| /** |
| - * Destructor. |
| + * Protected constructor. |
| + * |
| + * An MSI database handle is an overloaded type, used both for installation databases and one opened outside an installation. |
| + * These database handles, while both databases, have different capabilities and are thus defined in subclasses. |
| + * Each subclass has the responsibility for obtaining a database handle appropriate to its circumstance. |
| + * |
| + * \sa MSDN "Obtaining a Database Handle" |
| + * http://msdn.microsoft.com/en-us/library/windows/desktop/aa370541(v=vs.85).aspx |
| */ |
| - ~Database(); |
| + Database( MSIHANDLE handle ) |
| + : handle( handle ) |
| + {} |
| -protected: |
| /** |
| */ |
| - MSIHANDLE handle; |
| + handle_type handle ; |
| private: |
| /** |
| * Private copy constructor is declared but not defined. |
| */ |
| - Database( const Database & ); |
| + Database( const Database & ) ; |
| /** |
| * Private assignment operator is declared but not defined. |
| */ |
| Database & operator=( const Database & ) ; |
| -}; |
| + |
| + /** |
| + * Open a new view for this database. |
| + * |
| + * \param query |
| + * An SQL query using the restricted MSI syntax |
| + * |
| + * \sa |
| + * - MSDN [MsiDatabaseOpenView function](http://msdn.microsoft.com/en-us/library/aa370082%28v=vs.85%29.aspx) |
| + */ |
| + msi_handle open_view( const wchar_t * query ) ; |
| + |
| + friend class View ; |
| +} ; |
| /** |
| * A Windows Installer database in an installation context. |
| @@ -61,14 +89,115 @@ |
| /** |
| * The constructor of a database in an installation context has no arguments because the database is a part of that context. |
| */ |
| - Installation_Database( Immediate_Session & session ); |
| -}; |
| + Installation_Database( Immediate_Session & session ) ; |
| +} ; |
| +//------------------------------------------------------- |
| +// |
| +//------------------------------------------------------- |
| /** |
| - * A Windows Installer database in a non-installation context. |
| + * A Windows Installer database outside of an installation context, opened as a file from the file system. |
| + * |
| + * This is a read-only version of a file-system database. |
| + * Refactor the class to obtain other open-modes. |
| + * |
| */ |
| -class Non_Installation_Database : public Database |
| +class File_System_Database : public Database |
| { |
| -}; |
| + /** |
| + * Open function is separate to enable initializing base class before constructor body. |
| + * |
| + * \sa |
| + * - MSDN [MsiOpenDatabase function](http://msdn.microsoft.com/en-us/library/aa370338%28v=vs.85%29.aspx) |
| + */ |
| + msi_handle handle_from_pathname( const wchar_t * pathname ) |
| + { |
| + MSIHANDLE handle ; |
| + UINT x = MsiOpenDatabaseW( pathname, MSIDBOPEN_READONLY, & handle ) ; |
| + if ( x != ERROR_SUCCESS ) |
| + { |
| + throw std::runtime_error( "Open database from file system failed" ) ; |
| + } |
| + return msi_handle( handle ) ; |
| + } |
| + |
| +public: |
| + File_System_Database( const wchar_t * pathname ) |
| + : Database( handle_from_pathname( pathname ) ) |
| + {} |
| +} ; |
| + |
| +//------------------------------------------------------- |
| +// View |
| +//------------------------------------------------------- |
| +/* |
| + * The MSI database is accessible through a cut-down version of SQL. |
| + * There's no distinction between view and query in this dialect. |
| + * |
| + * \sa |
| + * - MSDN [Working with Queries](http://msdn.microsoft.com/en-us/library/aa372879%28v=vs.85%29.aspx) |
| + */ |
| +class View |
| +{ |
| + /** |
| + * Policy class to close a view handle. |
| + * View handles don't get closed with the generic close function for other MSI handles. |
| + */ |
| + template< class T > |
| + struct View_Destruction |
| + { |
| + /** |
| + * \sa MSDN [MsiViewClose function](http://msdn.microsoft.com/en-us/library/aa370510%28v=vs.85%29.aspx) |
| + */ |
| + inline static void close( T handle ) |
| + { |
| + ::MsiViewClose( handle ) ; |
| + } |
| + } ; |
| + |
| + typedef handle< MSIHANDLE, Disallow_Null, View_Destruction > handle_type ; |
| + |
| + /** |
| + * Handle for the MSI view object |
| + */ |
| + handle_type _handle; |
| + |
| +public: |
| + /** |
| + * Ordinary constructor |
| + */ |
| + View( Database & db, wchar_t * query ) |
| + : _handle( db.open_view( query ) ) |
| + {} |
| + |
| + /** |
| + * Execute the query and return the first record in its results. |
| + * |
| + * \param arguments |
| + * List of parameters to supply as the query arguments (question marks). |
| + */ |
| + Record first( Record & arguments ) ; |
| + |
| + /** |
| + * Execute the query and return the first record in its results. |
| + * |
| + * With no arguments, this version of the function may only be used with a query that takes no arguments. |
| + */ |
| + Record first() ; |
| + |
| + /** |
| + * Retrieve the next record. |
| + */ |
| + Record next() ; |
| + |
| + /** |
| + * End marker |
| + */ |
| + inline Record end() |
| + { |
| + return Record( Record::null_t() ) ; |
| + } |
| +} ; |
| + |
| #endif |