OLD | NEW |
1 /** | 1 /** |
2 * \file database.h MSI database | 2 * \file database.h MSI database |
3 */ | 3 */ |
4 | 4 |
5 #ifndef DATABASE_H | 5 #ifndef DATABASE_H |
6 #define DATABASE_H | 6 #define DATABASE_H |
7 | 7 |
8 #include <string> | 8 #include <string> |
9 #include "windows.h" | 9 #include <memory> |
10 #include "msi.h" | |
11 | 10 |
| 11 #include <Windows.h> |
| 12 #include <Msi.h> |
| 13 #include <MsiQuery.h> |
| 14 |
| 15 #include "handle.h" |
12 #include "session.h" | 16 #include "session.h" |
13 | 17 |
| 18 // Forward declarations |
| 19 class View ; |
| 20 |
| 21 //------------------------------------------------------- |
| 22 // Database |
| 23 //------------------------------------------------------- |
14 /** | 24 /** |
15 * A Windows Installer database as contained in an MSI file. | 25 * A Windows Installer database as contained in an MSI file. |
16 * | 26 * |
17 * The API for MSI databases is shared between installation and non-installation
contexts. | 27 * The API for MSI databases is shared between installation and non-installation
contexts. |
18 * Roughly speaking, outside an installation the database supports both read and
write, | 28 * Roughly speaking, outside an installation the database supports both read and
write, |
19 * but inside an installation the database is read-only. | 29 * but inside an installation the database is read-only. |
20 * The life cycle functions are not shared, in addition. | 30 * The life cycle functions are not shared, in addition. |
21 * Outside of these restrictions, however, the API is mostly common. | 31 * Outside of these restrictions, however, the API is mostly common. |
22 * This class is the base class for the common API. | 32 * This class is the base class for the common API. |
23 * Subclasses provide public constructors and provide access to API calls not in
common. | 33 * Subclasses provide public constructors and provide access to API calls not in
common. |
24 */ | 34 */ |
25 class Database | 35 class Database |
26 { | 36 { |
27 protected: | 37 protected: |
28 /** | 38 typedef handle< MSIHANDLE, Disallow_Null, MSI_Generic_Destruction > handle_typ
e ; |
29 * Protected constructor. Life cycle depends strongly on context. | |
30 */ | |
31 Database( MSIHANDLE handle ); | |
32 | 39 |
33 /** | 40 /** |
34 * Destructor. | 41 * Protected constructor. |
| 42 * |
| 43 * An MSI database handle is an overloaded type, used both for installation da
tabases and one opened outside an installation. |
| 44 * These database handles, while both databases, have different capabilities a
nd are thus defined in subclasses. |
| 45 * Each subclass has the responsibility for obtaining a database handle approp
riate to its circumstance. |
| 46 * |
| 47 * \sa MSDN "Obtaining a Database Handle" |
| 48 * http://msdn.microsoft.com/en-us/library/windows/desktop/aa370541(v=vs.85
).aspx |
35 */ | 49 */ |
36 ~Database(); | 50 Database( MSIHANDLE handle ) |
| 51 : handle( handle ) |
| 52 {} |
37 | 53 |
38 protected: | |
39 /** | 54 /** |
40 */ | 55 */ |
41 MSIHANDLE handle; | 56 handle_type handle ; |
42 | 57 |
43 private: | 58 private: |
44 /** | 59 /** |
45 * Private copy constructor is declared but not defined. | 60 * Private copy constructor is declared but not defined. |
46 */ | 61 */ |
47 Database( const Database & ); | 62 Database( const Database & ) ; |
48 | 63 |
49 /** | 64 /** |
50 * Private assignment operator is declared but not defined. | 65 * Private assignment operator is declared but not defined. |
51 */ | 66 */ |
52 Database & operator=( const Database & ) ; | 67 Database & operator=( const Database & ) ; |
53 }; | 68 |
| 69 /** |
| 70 * Open a new view for this database. |
| 71 * |
| 72 * \param query |
| 73 * An SQL query using the restricted MSI syntax |
| 74 * |
| 75 * \sa |
| 76 * - MSDN [MsiDatabaseOpenView function](http://msdn.microsoft.com/en-us/lib
rary/aa370082%28v=vs.85%29.aspx) |
| 77 */ |
| 78 msi_handle open_view( const wchar_t * query ) ; |
| 79 |
| 80 friend class View ; |
| 81 } ; |
54 | 82 |
55 /** | 83 /** |
56 * A Windows Installer database in an installation context. | 84 * A Windows Installer database in an installation context. |
57 */ | 85 */ |
58 class Installation_Database : public Database | 86 class Installation_Database : public Database |
59 { | 87 { |
60 public: | 88 public: |
61 /** | 89 /** |
62 * The constructor of a database in an installation context has no arguments b
ecause the database is a part of that context. | 90 * The constructor of a database in an installation context has no arguments b
ecause the database is a part of that context. |
63 */ | 91 */ |
64 Installation_Database( Immediate_Session & session ); | 92 Installation_Database( Immediate_Session & session ) ; |
65 }; | 93 } ; |
66 | 94 |
| 95 //------------------------------------------------------- |
| 96 // |
| 97 //------------------------------------------------------- |
67 /** | 98 /** |
68 * A Windows Installer database in a non-installation context. | 99 * A Windows Installer database outside of an installation context, opened as a
file from the file system. |
| 100 * |
| 101 * This is a read-only version of a file-system database. |
| 102 * Refactor the class to obtain other open-modes. |
| 103 * |
69 */ | 104 */ |
70 class Non_Installation_Database : public Database | 105 class File_System_Database : public Database |
71 { | 106 { |
72 }; | 107 /** |
| 108 * Open function is separate to enable initializing base class before construc
tor body. |
| 109 * |
| 110 * \sa |
| 111 * - MSDN [MsiOpenDatabase function](http://msdn.microsoft.com/en-us/library
/aa370338%28v=vs.85%29.aspx) |
| 112 */ |
| 113 msi_handle handle_from_pathname( const wchar_t * pathname ) |
| 114 { |
| 115 MSIHANDLE handle ; |
| 116 UINT x = MsiOpenDatabaseW( pathname, MSIDBOPEN_READONLY, & handle ) ; |
| 117 if ( x != ERROR_SUCCESS ) |
| 118 { |
| 119 throw std::runtime_error( "Open database from file system failed" ) ; |
| 120 } |
| 121 return msi_handle( handle ) ; |
| 122 } |
| 123 |
| 124 public: |
| 125 File_System_Database( const wchar_t * pathname ) |
| 126 : Database( handle_from_pathname( pathname ) ) |
| 127 {} |
| 128 } ; |
| 129 |
| 130 //------------------------------------------------------- |
| 131 // View |
| 132 //------------------------------------------------------- |
| 133 /* |
| 134 * The MSI database is accessible through a cut-down version of SQL. |
| 135 * There's no distinction between view and query in this dialect. |
| 136 * |
| 137 * \sa |
| 138 * - MSDN [Working with Queries](http://msdn.microsoft.com/en-us/library/aa372
879%28v=vs.85%29.aspx) |
| 139 */ |
| 140 class View |
| 141 { |
| 142 /** |
| 143 * Policy class to close a view handle. |
| 144 * View handles don't get closed with the generic close function for other MSI
handles. |
| 145 */ |
| 146 template< class T > |
| 147 struct View_Destruction |
| 148 { |
| 149 /** |
| 150 * \sa MSDN [MsiViewClose function](http://msdn.microsoft.com/en-us/library/
aa370510%28v=vs.85%29.aspx) |
| 151 */ |
| 152 inline static void close( T handle ) |
| 153 { |
| 154 ::MsiViewClose( handle ) ; |
| 155 } |
| 156 } ; |
| 157 |
| 158 typedef handle< MSIHANDLE, Disallow_Null, View_Destruction > handle_type ; |
| 159 |
| 160 /** |
| 161 * Handle for the MSI view object |
| 162 */ |
| 163 handle_type _handle; |
| 164 |
| 165 public: |
| 166 /** |
| 167 * Ordinary constructor |
| 168 */ |
| 169 View( Database & db, wchar_t * query ) |
| 170 : _handle( db.open_view( query ) ) |
| 171 {} |
| 172 |
| 173 /** |
| 174 * Execute the query and return the first record in its results. |
| 175 * |
| 176 * \param arguments |
| 177 * List of parameters to supply as the query arguments (question marks). |
| 178 */ |
| 179 Record first( Record & arguments ) ; |
| 180 |
| 181 /** |
| 182 * Execute the query and return the first record in its results. |
| 183 * |
| 184 * With no arguments, this version of the function may only be used with a que
ry that takes no arguments. |
| 185 */ |
| 186 Record first() ; |
| 187 |
| 188 /** |
| 189 * Retrieve the next record. |
| 190 */ |
| 191 Record next() ; |
| 192 |
| 193 /** |
| 194 * End marker |
| 195 */ |
| 196 inline Record end() |
| 197 { |
| 198 return Record( Record::null_t() ) ; |
| 199 } |
| 200 } ; |
| 201 |
73 | 202 |
74 #endif | 203 #endif |
OLD | NEW |