| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
| 2 | |
| 3 | namespace WixToolset.Dtf.WindowsInstaller |
| 4 | { |
| 5 | using System; |
| 6 | using System.IO; |
| 7 | using System.Text; |
| 8 | using System.Globalization; |
| 9 | using System.Runtime.InteropServices; |
| 10 | |
| 11 | /// <summary> |
| 12 | /// Provides access to summary information of a Windows Installer database. |
| 13 | /// </summary> |
| 14 | public class SummaryInfo : InstallerHandle |
| 15 | { |
| 16 | internal const int MAX_PROPERTIES = 20; |
| 17 | |
| 18 | /// <summary> |
| 19 | /// Gets a SummaryInfo object that can be used to examine, update, and add |
| 20 | /// properties to the summary information stream of a package or transform. |
| 21 | /// </summary> |
| 22 | /// <param name="packagePath">Path to the package (database) or transform</param> |
| 23 | /// <param name="enableWrite">True to reserve resources for writing summary information properties.</param> |
| 24 | /// <exception cref="FileNotFoundException">the package does not exist or could not be read</exception> |
| 25 | /// <exception cref="InstallerException">the package is an invalid format</exception> |
| 26 | /// <remarks><p> |
| 27 | /// The SummaryInfo object should be <see cref="InstallerHandle.Close"/>d after use. |
| 28 | /// It is best that the handle be closed manually as soon as it is no longer |
| 29 | /// needed, as leaving lots of unused handles open can degrade performance. |
| 30 | /// </p><p> |
| 31 | /// Win32 MSI API: |
| 32 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msigetsummaryinformation.asp">MsiGetSummaryInformation</a> |
| 33 | /// </p></remarks> |
| 34 | public SummaryInfo(string packagePath, bool enableWrite) |
| 35 | : base((IntPtr) SummaryInfo.OpenSummaryInfo(packagePath, enableWrite), true) |
| 36 | { |
| 37 | } |
| 38 | |
| 39 | internal SummaryInfo(IntPtr handle, bool ownsHandle) : base(handle, ownsHandle) |
| 40 | { |
| 41 | } |
| 42 | |
| 43 | /// <summary>Gets or sets the Title summary information property.</summary> |
| 44 | /// <remarks><p> |
| 45 | /// The Title summary information property briefly describes the type of installer package. Phrases |
| 46 | /// such as "Installation Database" or "Transform" or "Patch" may be used for this property. |
| 47 | /// </p><p> |
| 48 | /// Win32 MSI APIs: |
| 49 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfogetproperty.asp">MsiSummaryInfoGetProperty</a>, |
| 50 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfosetproperty.asp">MsiSummaryInfoSetProperty</a> |
| 51 | /// </p></remarks> |
| 52 | public string Title |
| 53 | { |
| 54 | get { return this[2]; } |
| 55 | set { this[2] = value; } |
| 56 | } |
| 57 | |
| 58 | /// <summary>Gets or sets the Subject summary information property.</summary> |
| 59 | /// <remarks><p> |
| 60 | /// The Subject summary information property conveys to a file browser the product that can be installed using |
| 61 | /// the logic and data in this installer database. For example, the value of the summary property for |
| 62 | /// Microsoft Office 97 would be "Microsoft Office 97 Professional". This value is typically set from the |
| 63 | /// installer property ProductName. |
| 64 | /// </p><p> |
| 65 | /// Win32 MSI APIs: |
| 66 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfogetproperty.asp">MsiSummaryInfoGetProperty</a>, |
| 67 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfosetproperty.asp">MsiSummaryInfoSetProperty</a> |
| 68 | /// </p></remarks> |
| 69 | public string Subject |
| 70 | { |
| 71 | get { return this[3]; } |
| 72 | set { this[3] = value; } |
| 73 | } |
| 74 | |
| 75 | /// <summary>Gets or sets the Author summary information property.</summary> |
| 76 | /// <remarks><p> |
| 77 | /// The Author summary information property conveys to a file browser the manufacturer of the installation |
| 78 | /// database. This value is typically set from the installer property Manufacturer. |
| 79 | /// </p><p> |
| 80 | /// Win32 MSI APIs: |
| 81 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfogetproperty.asp">MsiSummaryInfoGetProperty</a>, |
| 82 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfosetproperty.asp">MsiSummaryInfoSetProperty</a> |
| 83 | /// </p></remarks> |
| 84 | public string Author |
| 85 | { |
| 86 | get { return this[4]; } |
| 87 | set { this[4] = value; } |
| 88 | } |
| 89 | |
| 90 | /// <summary>Gets or sets the Keywords summary information property.</summary> |
| 91 | /// <remarks><p> |
| 92 | /// The Keywords summary information property is used by file browsers to hold keywords that permit the |
| 93 | /// database file to be found in a keyword search. The set of keywords typically includes "Installer" as |
| 94 | /// well as product-specific keywords, and may be localized. |
| 95 | /// </p><p> |
| 96 | /// Win32 MSI APIs: |
| 97 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfogetproperty.asp">MsiSummaryInfoGetProperty</a>, |
| 98 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfosetproperty.asp">MsiSummaryInfoSetProperty</a> |
| 99 | /// </p></remarks> |
| 100 | public string Keywords |
| 101 | { |
| 102 | get { return this[5]; } |
| 103 | set { this[5] = value; } |
| 104 | } |
| 105 | |
| 106 | /// <summary>Gets or sets the Comments summary information property.</summary> |
| 107 | /// <remarks><p> |
| 108 | /// The Comments summary information property conveys the general purpose of the installer database. By convention, |
| 109 | /// the value for this summary property is set to the following: |
| 110 | /// </p><p> |
| 111 | /// "This installer database contains the logic and data required to install <product name>." |
| 112 | /// </p><p> |
| 113 | /// where <product name> is the name of the product being installed. In general the value for this summary |
| 114 | /// property only changes in the product name, nothing else. |
| 115 | /// </p><p> |
| 116 | /// Win32 MSI APIs: |
| 117 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfogetproperty.asp">MsiSummaryInfoGetProperty</a>, |
| 118 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfosetproperty.asp">MsiSummaryInfoSetProperty</a> |
| 119 | /// </p></remarks> |
| 120 | public string Comments |
| 121 | { |
| 122 | get { return this[6]; } |
| 123 | set { this[6] = value; } |
| 124 | } |
| 125 | |
| 126 | /// <summary>Gets or sets the Template summary information property.</summary> |
| 127 | /// <remarks><p> |
| 128 | /// The Template summary information propery indicates the platform and language versions supported by the database. |
| 129 | /// </p><p> |
| 130 | /// The syntax of the Template Summary property information is: |
| 131 | /// [platform property][,platform property][,...];[language id][,language id][,...] |
| 132 | /// </p><p> |
| 133 | /// For example, the following are all valid values for the Template Summary property: |
| 134 | /// <list type="bullet"> |
| 135 | /// <item>Intel;1033</item> |
| 136 | /// <item>Intel64;1033</item> |
| 137 | /// <item>;1033</item> |
| 138 | /// <item>;</item> |
| 139 | /// <item>Intel ;1033,2046</item> |
| 140 | /// <item>Intel64;1033,2046</item> |
| 141 | /// <item>Intel;0</item> |
| 142 | /// </list> |
| 143 | /// </p><p> |
| 144 | /// If this is a 64-bit Windows Installer, enter Intel64 in the Template summary information property. Note that an |
| 145 | /// installation package cannot have both the Intel and Intel64 properties set. |
| 146 | /// </p><p> |
| 147 | /// If the current platform does not match one of the platforms specified then the installer will not process the |
| 148 | /// package. Not specifying a platform implies that the package is platform-independent. |
| 149 | /// </p><p> |
| 150 | /// Entering 0 in the language ID field of the Template summary information property, or leaving this field empty, |
| 151 | /// indicates that the package is language neutral. |
| 152 | /// </p><p> |
| 153 | /// There are variations of this property depending on whether it is in a source installer database or a transform. |
| 154 | /// </p><p> |
| 155 | /// Source Installer Database - Only one language can be specified in a source installer database. Merge Modules are |
| 156 | /// the only packages that may have multiple languages. For more information, see Multiple Language Merge Modules. |
| 157 | /// </p><p> |
| 158 | /// Transform - In a transform file, only one language may be specified. The specified platform and language determine |
| 159 | /// whether a transform can be applied to a particular database. The platform property and the language property can |
| 160 | /// be left blank if no transform restriction relies on them to validate the transform. |
| 161 | /// </p><p> |
| 162 | /// This summary property is REQUIRED. |
| 163 | /// </p><p> |
| 164 | /// Win32 MSI APIs: |
| 165 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfogetproperty.asp">MsiSummaryInfoGetProperty</a>, |
| 166 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfosetproperty.asp">MsiSummaryInfoSetProperty</a> |
| 167 | /// </p></remarks> |
| 168 | public string Template |
| 169 | { |
| 170 | get { return this[7]; } |
| 171 | set { this[7] = value; } |
| 172 | } |
| 173 | |
| 174 | /// <summary>Gets or sets the LastSavedBy summary information property.</summary> |
| 175 | /// <remarks><p> |
| 176 | /// The installer sets the Last Saved By summary information property to the value of the LogonUser property during |
| 177 | /// an administrative installation. The installer never uses this property and a user never needs to modify it. |
| 178 | /// Developers of a database editing tool may use this property to track the last person to modify the database. |
| 179 | /// This property should be left set to null in a final shipping database. |
| 180 | /// </p><p> |
| 181 | /// In a transform, this summary property contains the platform and language ID(s) that a database should have |
| 182 | /// after it has been transformed. The property specifies to what the Template should be set in the new database. |
| 183 | /// </p><p> |
| 184 | /// Win32 MSI APIs: |
| 185 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfogetproperty.asp">MsiSummaryInfoGetProperty</a>, |
| 186 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfosetproperty.asp">MsiSummaryInfoSetProperty</a> |
| 187 | /// </p></remarks> |
| 188 | public string LastSavedBy |
| 189 | { |
| 190 | get { return this[8]; } |
| 191 | set { this[8] = value; } |
| 192 | } |
| 193 | |
| 194 | /// <summary>Gets or sets the RevisionNumber summary information property.</summary> |
| 195 | /// <remarks><p> |
| 196 | /// The Revision Number summary information property contains the package code for the installer package. The |
| 197 | /// package code is a unique identifier of the installer package. |
| 198 | /// </p><p> |
| 199 | /// The Revision Number summary information property of a patch package specifies the GUID patch code for |
| 200 | /// the patch. This is followed by a list of patch code GUIDs for obsolete patches that are removed when this |
| 201 | /// patch is applied. The patch codes are concatenated with no delimiters separating GUIDs in the list. |
| 202 | /// </p><p> |
| 203 | /// The Revision Number summary information property of a transform package lists the product code GUIDs |
| 204 | /// and version of the new and original products and the upgrade code GUID. The list is separated with |
| 205 | /// semicolons as follows. |
| 206 | /// </p><p> |
| 207 | /// Original-Product-Code Original-Product-Version ; New-Product Code New-Product-Version; Upgrade-Code |
| 208 | /// </p><p> |
| 209 | /// This summary property is REQUIRED. |
| 210 | /// </p><p> |
| 211 | /// Win32 MSI APIs: |
| 212 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfogetproperty.asp">MsiSummaryInfoGetProperty</a>, |
| 213 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfosetproperty.asp">MsiSummaryInfoSetProperty</a> |
| 214 | /// </p></remarks> |
| 215 | public string RevisionNumber |
| 216 | { |
| 217 | get { return this[9]; } |
| 218 | set { this[9] = value; } |
| 219 | } |
| 220 | |
| 221 | /// <summary>Gets or sets the CreatingApp summary information property.</summary> |
| 222 | /// <remarks><p> |
| 223 | /// The CreatingApp summary information property conveys which application created the installer database. |
| 224 | /// In general the value for this summary property is the name of the software used to author this database. |
| 225 | /// </p><p> |
| 226 | /// Win32 MSI APIs: |
| 227 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfogetproperty.asp">MsiSummaryInfoGetProperty</a>, |
| 228 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfosetproperty.asp">MsiSummaryInfoSetProperty</a> |
| 229 | /// </p></remarks> |
| 230 | public string CreatingApp |
| 231 | { |
| 232 | get { return this[18]; } |
| 233 | set { this[18] = value; } |
| 234 | } |
| 235 | |
| 236 | /// <summary>Gets or sets the LastPrintTime summary information property.</summary> |
| 237 | /// <remarks><p> |
| 238 | /// The LastPrintTime summary information property can be set to the date and time during an administrative |
| 239 | /// installation to record when the administrative image was created. For non-administrative installations |
| 240 | /// this property is the same as the CreateTime summary information property. |
| 241 | /// </p><p> |
| 242 | /// Win32 MSI APIs: |
| 243 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfogetproperty.asp">MsiSummaryInfoGetProperty</a>, |
| 244 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfosetproperty.asp">MsiSummaryInfoSetProperty</a> |
| 245 | /// </p></remarks> |
| 246 | public DateTime LastPrintTime |
| 247 | { |
| 248 | get { return (DateTime) this[11, typeof(DateTime)]; } |
| 249 | set { this[11, typeof(DateTime)] = value; } |
| 250 | } |
| 251 | |
| 252 | /// <summary>Gets or sets the CreateTime summary information property.</summary> |
| 253 | /// <remarks><p> |
| 254 | /// The CreateTime summary information property conveys when the installer database was created. |
| 255 | /// </p><p> |
| 256 | /// Win32 MSI APIs: |
| 257 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfogetproperty.asp">MsiSummaryInfoGetProperty</a>, |
| 258 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfosetproperty.asp">MsiSummaryInfoSetProperty</a> |
| 259 | /// </p></remarks> |
| 260 | public DateTime CreateTime |
| 261 | { |
| 262 | get { return (DateTime) this[12, typeof(DateTime)]; } |
| 263 | set { this[12, typeof(DateTime)] = value; } |
| 264 | } |
| 265 | |
| 266 | /// <summary>Gets or sets the LastSaveTime summary information property.</summary> |
| 267 | /// <remarks><p> |
| 268 | /// The LastSaveTime summary information property conveys when the last time the installer database was |
| 269 | /// modified. Each time a user changes an installation the value for this summary property is updated to |
| 270 | /// the current system time/date at the time the installer database was saved. Initially the value for |
| 271 | /// this summary property is set to null to indicate that no changes have yet been made. |
| 272 | /// </p><p> |
| 273 | /// Win32 MSI APIs: |
| 274 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfogetproperty.asp">MsiSummaryInfoGetProperty</a>, |
| 275 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfosetproperty.asp">MsiSummaryInfoSetProperty</a> |
| 276 | /// </p></remarks> |
| 277 | public DateTime LastSaveTime |
| 278 | { |
| 279 | get { return (DateTime) this[13, typeof(DateTime)]; } |
| 280 | set { this[13, typeof(DateTime)] = value; } |
| 281 | } |
| 282 | |
| 283 | /// <summary>Gets or sets the CodePage summary information property.</summary> |
| 284 | /// <remarks><p> |
| 285 | /// The Codepage summary information property is the numeric value of the ANSI code page used for any |
| 286 | /// strings that are stored in the summary information. Note that this is not the same code page for |
| 287 | /// strings in the installation database. The Codepage summary information property is used to translate |
| 288 | /// the strings in the summary information into Unicode when calling the Unicode API functions. The |
| 289 | /// Codepage summary information property must be set before any string properties are set in the |
| 290 | /// summary information. |
| 291 | /// </p><p> |
| 292 | /// Win32 MSI APIs: |
| 293 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfogetproperty.asp">MsiSummaryInfoGetProperty</a>, |
| 294 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfosetproperty.asp">MsiSummaryInfoSetProperty</a> |
| 295 | /// </p></remarks> |
| 296 | public short CodePage |
| 297 | { |
| 298 | get { return (short) this[1, typeof(short)]; } |
| 299 | set { this[1, typeof(short)] = value; } |
| 300 | } |
| 301 | |
| 302 | /// <summary>Gets or sets the PageCount summary information property.</summary> |
| 303 | /// <remarks><p> |
| 304 | /// For an installation package, the PageCount summary information property contains the minimum |
| 305 | /// installer version required. For Windows Installer version 1.0, this property must be set to the |
| 306 | /// integer 100. For 64-bit Windows Installer Packages, this property must be set to the integer 200. |
| 307 | /// </p><p> |
| 308 | /// For a transform package, the PageCount summary information property contains minimum installer |
| 309 | /// version required to process the transform. Set to the greater of the two PageCount summary information |
| 310 | /// property values belonging to the databases used to generate the transform. |
| 311 | /// </p><p> |
| 312 | /// The PageCount summary information property is set to null in patch packages. |
| 313 | /// </p><p> |
| 314 | /// This summary property is REQUIRED. |
| 315 | /// </p><p> |
| 316 | /// Win32 MSI APIs: |
| 317 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfogetproperty.asp">MsiSummaryInfoGetProperty</a>, |
| 318 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfosetproperty.asp">MsiSummaryInfoSetProperty</a> |
| 319 | /// </p></remarks> |
| 320 | public int PageCount |
| 321 | { |
| 322 | get { return (int) this[14, typeof(int)]; } |
| 323 | set { this[14, typeof(int)] = value; } |
| 324 | } |
| 325 | |
| 326 | /// <summary>Gets or sets the WordCount summary information property.</summary> |
| 327 | /// <remarks><p> |
| 328 | /// The WordCount summary information property indicates the type of source file image. If this property is |
| 329 | /// not present, it defaults to 0. Note that this property is stored in place of the standard Count property. |
| 330 | /// </p><p> |
| 331 | /// This property is a bit field. New bits may be added in the future. At present the following bits are |
| 332 | /// available: |
| 333 | /// <list type="bullet"> |
| 334 | /// <item>Bit 0: 0 = long file names, 1 = short file names</item> |
| 335 | /// <item>Bit 1: 0 = source is uncompressed, 1 = source is compressed</item> |
| 336 | /// <item>Bit 2: 0 = source is original media, 1 = source is administrative installation</item> |
| 337 | /// <item>[MSI 4.0] Bit 3: 0 = elevated privileges can be required to install, 1 = elevated privileges are not required to install</item> |
| 338 | /// </list> |
| 339 | /// </p><p> |
| 340 | /// These are combined to give the WordCount summary information property one of the following values |
| 341 | /// indicating a type of source file image: |
| 342 | /// <list type="bullet"> |
| 343 | /// <item>0 - Original source using long file names. Matches tree in Directory table.</item> |
| 344 | /// <item>1 - Original source using short file names. Matches tree in Directory table.</item> |
| 345 | /// <item>2 - Compressed source files using long file names. Matches cabinets and files in the Media table.</item> |
| 346 | /// <item>3 - Compressed source files using short file names. Matches cabinets and files in the Media table.</item> |
| 347 | /// <item>4 - Administrative image using long file names. Matches tree in Directory table.</item> |
| 348 | /// <item>5 - Administrative image using short file names. Matches tree in Directory table.</item> |
| 349 | /// </list> |
| 350 | /// </p><p> |
| 351 | /// Note that if the package is marked as compressed (bit 1 is set), the installer only installs files |
| 352 | /// located at the root of the source. In this case, even files marked as uncompressed in the File table must |
| 353 | /// be located at the root to be installed. To specify a source image that has both a cabinet file (compressed |
| 354 | /// files) and uncompressed files that match the tree in the Directory table, mark the package as uncompressed |
| 355 | /// by leaving bit 1 unset (value=0) in the WordCount summary information property and set |
| 356 | /// <see cref="FileAttributes.Compressed"/> (value=16384) in the Attributes column of the File table |
| 357 | /// for each file in the cabinet. |
| 358 | /// </p><p> |
| 359 | /// For a patch package, the WordCount summary information property specifies the patch engine that was used |
| 360 | /// to create the patch files. The default value is 1 and indicates that MSPATCH was used to create the patch |
| 361 | /// A value of "2" means that the patch is using smaller, optimized, files available only with Windows Installer |
| 362 | /// version 1.2 or later. A patch with a WordCount of "2" fails immediately if used with a Windows Installer |
| 363 | /// version earlier than 1.2. A patch with a WordCount of "3" fails immediately if used with a Windows Installer |
| 364 | /// version earlier than 2.0. |
| 365 | /// </p><p> |
| 366 | /// This summary property is REQUIRED. |
| 367 | /// </p><p> |
| 368 | /// Win32 MSI APIs: |
| 369 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfogetproperty.asp">MsiSummaryInfoGetProperty</a>, |
| 370 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfosetproperty.asp">MsiSummaryInfoSetProperty</a> |
| 371 | /// </p></remarks> |
| 372 | public int WordCount |
| 373 | { |
| 374 | get { return (int) this[15, typeof(int)]; } |
| 375 | set { this[15, typeof(int)] = value; } |
| 376 | } |
| 377 | |
| 378 | /// <summary>Gets or sets the CharacterCount summary information property.</summary> |
| 379 | /// <remarks><p> |
| 380 | /// The CharacterCount summary information property is only used in transforms. This part of the summary |
| 381 | /// information stream is divided into two 16-bit words. The upper word contains the transform validation |
| 382 | /// flags. The lower word contains the transform error condition flags. |
| 383 | /// </p><p> |
| 384 | /// Win32 MSI APIs: |
| 385 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfogetproperty.asp">MsiSummaryInfoGetProperty</a>, |
| 386 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfosetproperty.asp">MsiSummaryInfoSetProperty</a> |
| 387 | /// </p></remarks> |
| 388 | public int CharacterCount |
| 389 | { |
| 390 | get { return (int) this[16, typeof(int)]; } |
| 391 | set { this[16, typeof(int)] = value; } |
| 392 | } |
| 393 | |
| 394 | /// <summary>Gets or sets the Security summary information property.</summary> |
| 395 | /// <remarks><p> |
| 396 | /// The Security summary information property conveys whether the package should be opened as read-only. The database |
| 397 | /// editing tool should not modify a read-only enforced database and should issue a warning at attempts to modify a |
| 398 | /// read-only recommended database. The following values of this property are applicable to Windows Installer files: |
| 399 | /// <list type="bullet"> |
| 400 | /// <item>0 - no restriction</item> |
| 401 | /// <item>2 - read only recommended</item> |
| 402 | /// <item>4 - read only enforced</item> |
| 403 | /// </list> |
| 404 | /// </p><p> |
| 405 | /// This property should be set to read-only recommended (2) for an installation database and to read-only |
| 406 | /// enforced (4) for a transform or patch. |
| 407 | /// </p><p> |
| 408 | /// Win32 MSI APIs: |
| 409 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfogetproperty.asp">MsiSummaryInfoGetProperty</a>, |
| 410 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfosetproperty.asp">MsiSummaryInfoSetProperty</a> |
| 411 | /// </p></remarks> |
| 412 | public int Security |
| 413 | { |
| 414 | get { return (int) this[19, typeof(int)]; } |
| 415 | set { this[19, typeof(int)] = value; } |
| 416 | } |
| 417 | |
| 418 | private object this[uint property, Type type] |
| 419 | { |
| 420 | get |
| 421 | { |
| 422 | uint dataType; |
| 423 | StringBuilder stringValue = new StringBuilder(""); |
| 424 | uint bufSize = 0; |
| 425 | int intValue; |
| 426 | long timeValue = 0; |
| 427 | |
| 428 | uint ret = RemotableNativeMethods.MsiSummaryInfoGetProperty( |
| 429 | (int) this.Handle, |
| 430 | property, |
| 431 | out dataType, |
| 432 | out intValue, |
| 433 | ref timeValue, |
| 434 | stringValue, |
| 435 | ref bufSize); |
| 436 | if (ret != 0 && dataType != (uint) VarEnum.VT_LPSTR) |
| 437 | { |
| 438 | throw InstallerException.ExceptionFromReturnCode(ret); |
| 439 | } |
| 440 | |
| 441 | switch ((VarEnum) dataType) |
| 442 | { |
| 443 | case VarEnum.VT_EMPTY: |
| 444 | { |
| 445 | if (type == typeof(DateTime)) |
| 446 | { |
| 447 | return DateTime.MinValue; |
| 448 | } |
| 449 | else if (type == typeof(string)) |
| 450 | { |
| 451 | return String.Empty; |
| 452 | } |
| 453 | else if (type == typeof(short)) |
| 454 | { |
| 455 | return (short) 0; |
| 456 | } |
| 457 | else |
| 458 | { |
| 459 | return (int) 0; |
| 460 | } |
| 461 | } |
| 462 | |
| 463 | case VarEnum.VT_LPSTR: |
| 464 | { |
| 465 | if (ret == (uint) NativeMethods.Error.MORE_DATA) |
| 466 | { |
| 467 | stringValue.Capacity = (int) ++bufSize; |
| 468 | ret = RemotableNativeMethods.MsiSummaryInfoGetProperty( |
| 469 | (int) this.Handle, |
| 470 | property, |
| 471 | out dataType, |
| 472 | out intValue, |
| 473 | ref timeValue, |
| 474 | stringValue, |
| 475 | ref bufSize); |
| 476 | } |
| 477 | if (ret != 0) |
| 478 | { |
| 479 | throw InstallerException.ExceptionFromReturnCode(ret); |
| 480 | } |
| 481 | return stringValue.ToString(); |
| 482 | } |
| 483 | |
| 484 | case VarEnum.VT_I2: |
| 485 | case VarEnum.VT_I4: |
| 486 | { |
| 487 | if (type == typeof(string)) |
| 488 | { |
| 489 | return intValue.ToString(CultureInfo.InvariantCulture); |
| 490 | } |
| 491 | else if (type == typeof(short)) |
| 492 | { |
| 493 | return (short) intValue; |
| 494 | } |
| 495 | else |
| 496 | { |
| 497 | return intValue; |
| 498 | } |
| 499 | } |
| 500 | |
| 501 | case VarEnum.VT_FILETIME: |
| 502 | { |
| 503 | if (type == typeof(string)) |
| 504 | { |
| 505 | return DateTime.FromFileTime(timeValue).ToString(CultureInfo.InvariantCulture); |
| 506 | } |
| 507 | else |
| 508 | { |
| 509 | return DateTime.FromFileTime(timeValue); |
| 510 | } |
| 511 | } |
| 512 | |
| 513 | default: |
| 514 | { |
| 515 | throw new InstallerException(); |
| 516 | } |
| 517 | } |
| 518 | } |
| 519 | |
| 520 | set |
| 521 | { |
| 522 | uint dataType = (uint) VarEnum.VT_NULL; |
| 523 | string stringValue = ""; |
| 524 | int intValue = 0; |
| 525 | long timeValue = 0; |
| 526 | |
| 527 | if (type == typeof(short)) |
| 528 | { |
| 529 | dataType = (uint) VarEnum.VT_I2; |
| 530 | intValue = (int)(short) value; // Double cast because value is a *boxed* short. |
| 531 | } |
| 532 | else if (type == typeof(int)) |
| 533 | { |
| 534 | dataType = (uint) VarEnum.VT_I4; |
| 535 | intValue = (int) value; |
| 536 | } |
| 537 | else if (type == typeof(string)) |
| 538 | { |
| 539 | dataType = (uint) VarEnum.VT_LPSTR; |
| 540 | stringValue = (string) value; |
| 541 | } |
| 542 | else // (type == typeof(DateTime)) |
| 543 | { |
| 544 | dataType = (uint) VarEnum.VT_FILETIME; |
| 545 | timeValue = ((DateTime) value).ToFileTime(); |
| 546 | } |
| 547 | |
| 548 | uint ret = NativeMethods.MsiSummaryInfoSetProperty( |
| 549 | (int) this.Handle, |
| 550 | property, |
| 551 | dataType, |
| 552 | intValue, |
| 553 | ref timeValue, |
| 554 | stringValue); |
| 555 | if (ret != 0) |
| 556 | { |
| 557 | throw InstallerException.ExceptionFromReturnCode(ret); |
| 558 | } |
| 559 | } |
| 560 | } |
| 561 | |
| 562 | private string this[uint property] |
| 563 | { |
| 564 | get { return (string) this[property, typeof(string)]; } |
| 565 | set { this[property, typeof(string)] = value; } |
| 566 | } |
| 567 | |
| 568 | /// <summary> |
| 569 | /// Formats and writes the previously stored properties into the standard summary information stream. |
| 570 | /// </summary> |
| 571 | /// <exception cref="InstallerException">The stream cannot be successfully written.</exception> |
| 572 | /// <remarks><p> |
| 573 | /// This method may only be called once after all the property values have been set. Properties may |
| 574 | /// still be read after the stream is written. |
| 575 | /// </p><p> |
| 576 | /// Win32 MSI API: |
| 577 | /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisummaryinfopersist.asp">MsiSummaryInfoPersist</a> |
| 578 | /// </p></remarks> |
| 579 | public void Persist() |
| 580 | { |
| 581 | uint ret = NativeMethods.MsiSummaryInfoPersist((int) this.Handle); |
| 582 | if (ret != 0) |
| 583 | { |
| 584 | throw InstallerException.ExceptionFromReturnCode(ret); |
| 585 | } |
| 586 | } |
| 587 | |
| 588 | private static int OpenSummaryInfo(string packagePath, bool enableWrite) |
| 589 | { |
| 590 | int summaryInfoHandle; |
| 591 | int maxProperties = !enableWrite ? 0 : SummaryInfo.MAX_PROPERTIES; |
| 592 | uint ret = RemotableNativeMethods.MsiGetSummaryInformation( |
| 593 | 0, |
| 594 | packagePath, |
| 595 | (uint) maxProperties, |
| 596 | out summaryInfoHandle); |
| 597 | if (ret != 0) |
| 598 | { |
| 599 | if (ret == (uint) NativeMethods.Error.FILE_NOT_FOUND || |
| 600 | ret == (uint) NativeMethods.Error.ACCESS_DENIED) |
| 601 | { |
| 602 | throw new FileNotFoundException(null, packagePath); |
| 603 | } |
| 604 | else |
| 605 | { |
| 606 | throw InstallerException.ExceptionFromReturnCode(ret); |
| 607 | } |
| 608 | } |
| 609 | return summaryInfoHandle; |
| 610 | } |
| 611 | } |
| 612 | } |