// 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. namespace WixToolset.Msi { using System; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Text; using System.Runtime.InteropServices; using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME; using WixToolset.Core.Native; /// /// Summary information for the MSI files. /// internal sealed class SummaryInformation : MsiHandle { /// /// Summary information properties for transforms. /// public enum Transform { /// PID_CODEPAGE = code page for the summary information stream CodePage = 1, /// PID_TITLE = typically just "Transform" Title = 2, /// PID_SUBJECT = original subject of target TargetSubject = 3, /// PID_AUTHOR = original manufacturer of target TargetManufacturer = 4, /// PID_KEYWORDS = keywords for the transform, typically including at least "Installer" Keywords = 5, /// PID_COMMENTS = describes what this package does Comments = 6, /// PID_TEMPLATE = target platform;language TargetPlatformAndLanguage = 7, /// PID_LASTAUTHOR = updated platform;language UpdatedPlatformAndLanguage = 8, /// PID_REVNUMBER = {productcode}version;{newproductcode}newversion;upgradecode ProductCodes = 9, /// PID_LASTPRINTED should be null for transforms Reserved11 = 11, ///.PID_CREATE_DTM = the timestamp when the transform was created CreationTime = 12, /// PID_PAGECOUNT = minimum installer version InstallerRequirement = 14, /// PID_CHARCOUNT = validation and error flags ValidationFlags = 16, /// PID_APPNAME = the application that created the transform CreatingApplication = 18, /// PID_SECURITY = whether read-only is enforced; should always be 4 for transforms Security = 19, } /// /// Summary information properties for patches. /// public enum Patch { /// PID_CODEPAGE = code page of the summary information stream CodePage = 1, /// PID_TITLE = a brief description of the package type Title = 2, /// PID_SUBJECT = package name PackageName = 3, /// PID_AUTHOR = manufacturer of the patch package Manufacturer = 4, /// PID_KEYWORDS = alternate sources for the patch package Sources = 5, /// PID_COMMENTS = general purpose of the patch package Comments = 6, /// PID_TEMPLATE = semicolon delimited list of ProductCodes ProductCodes = 7, /// PID_LASTAUTHOR = semicolon delimited list of transform names TransformNames = 8, /// PID_REVNUMBER = GUID patch code PatchCode = 9, /// PID_LASTPRINTED should be null for patches Reserved11 = 11, /// PID_PAGECOUNT should be null for patches Reserved14 = 14, /// PID_WORDCOUNT = minimum installer version InstallerRequirement = 15, /// PID_CHARCOUNT should be null for patches Reserved16 = 16, /// PID_SECURITY = read-only attribute of the patch package Security = 19, } /// /// Summary information values for the InstallerRequirement property. /// public enum InstallerRequirement { /// Any version of the installer will do Version10 = 1, /// At least 1.2 Version12 = 2, /// At least 2.0 Version20 = 3, /// At least 3.0 Version30 = 4, /// At least 3.1 Version31 = 5, } /// /// Instantiate a new SummaryInformation class from an open database. /// /// Database to retrieve summary information from. public SummaryInformation(Database db) { if (null == db) { throw new ArgumentNullException("db"); } uint handle = 0; int error = MsiInterop.MsiGetSummaryInformation(db.Handle, null, 0, ref handle); if (0 != error) { throw new MsiException(error); } this.Handle = handle; } /// /// Instantiate a new SummaryInformation class from a database file. /// /// The database file. public SummaryInformation(string databaseFile) { if (null == databaseFile) { throw new ArgumentNullException("databaseFile"); } uint handle = 0; int error = MsiInterop.MsiGetSummaryInformation(0, databaseFile, 0, ref handle); if (0 != error) { throw new MsiException(error); } this.Handle = handle; } /// /// Variant types in the summary information table. /// private enum VT : uint { /// Variant has not been assigned. EMPTY = 0, /// Null variant type. NULL = 1, /// 16-bit integer variant type. I2 = 2, /// 32-bit integer variant type. I4 = 3, /// String variant type. LPSTR = 30, /// Date time (FILETIME, converted to Variant time) variant type. FILETIME = 64, } /// /// Gets a summary information property. /// /// Index of the summary information property. /// The summary information property. public string GetProperty(int index) { uint dataType; StringBuilder stringValue = new StringBuilder(""); int bufSize = 0; int intValue; FILETIME timeValue; timeValue.dwHighDateTime = 0; timeValue.dwLowDateTime = 0; int error = MsiInterop.MsiSummaryInfoGetProperty(this.Handle, index, out dataType, out intValue, ref timeValue, stringValue, ref bufSize); if (234 == error) { stringValue.EnsureCapacity(++bufSize); error = MsiInterop.MsiSummaryInfoGetProperty(this.Handle, index, out dataType, out intValue, ref timeValue, stringValue, ref bufSize); } if (0 != error) { throw new MsiException(error); } switch ((VT)dataType) { case VT.EMPTY: return String.Empty; case VT.LPSTR: return stringValue.ToString(); case VT.I2: case VT.I4: return Convert.ToString(intValue, CultureInfo.InvariantCulture); case VT.FILETIME: long longFileTime = (((long)timeValue.dwHighDateTime) << 32) | unchecked((uint)timeValue.dwLowDateTime); DateTime dateTime = DateTime.FromFileTime(longFileTime); return dateTime.ToString("yyyy/MM/dd HH:mm:ss", CultureInfo.InvariantCulture); default: throw new InvalidOperationException(); } } } /// /// Summary information values for the CharCount property in transforms. /// [Flags] [SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")] public enum TransformFlags { /// Ignore error when adding a row that exists. ErrorAddExistingRow = 0x1, /// Ignore error when deleting a row that does not exist. ErrorDeleteMissingRow = 0x2, /// Ignore error when adding a table that exists. ErrorAddExistingTable = 0x4, /// Ignore error when deleting a table that does not exist. ErrorDeleteMissingTable = 0x8, /// Ignore error when updating a row that does not exist. ErrorUpdateMissingRow = 0x10, /// Ignore error when transform and database code pages do not match, and their code pages are neutral. ErrorChangeCodePage = 0x20, /// Default language must match base database. ValidateLanguage = 0x10000, /// Product must match base database. ValidateProduct = 0x20000, /// Check major version only. ValidateMajorVersion = 0x80000, /// Check major and minor versions only. ValidateMinorVersion = 0x100000, /// Check major, minor, and update versions. ValidateUpdateVersion = 0x200000, /// Installed version lt base version. ValidateNewLessBaseVersion = 0x400000, /// Installed version lte base version. ValidateNewLessEqualBaseVersion = 0x800000, /// Installed version eq base version. ValidateNewEqualBaseVersion = 0x1000000, /// Installed version gte base version. ValidateNewGreaterEqualBaseVersion = 0x2000000, /// Installed version gt base version. ValidateNewGreaterBaseVersion = 0x4000000, /// UpgradeCode must match base database. ValidateUpgradeCode = 0x8000000, /// Masks all version checks on ProductVersion. ProductVersionMask = ValidateMajorVersion | ValidateMinorVersion | ValidateUpdateVersion, /// Masks all operations on ProductVersion. ProductVersionOperatorMask = ValidateNewLessBaseVersion | ValidateNewLessEqualBaseVersion | ValidateNewEqualBaseVersion | ValidateNewGreaterEqualBaseVersion | ValidateNewGreaterBaseVersion, /// Default value for instance transforms. InstanceTransformDefault = ErrorAddExistingRow | ErrorDeleteMissingRow | ErrorAddExistingTable | ErrorDeleteMissingTable | ErrorUpdateMissingRow | ErrorChangeCodePage | ValidateProduct | ValidateUpdateVersion | ValidateNewGreaterEqualBaseVersion, /// Default value for language transforms. LanguageTransformDefault = ErrorAddExistingRow | ErrorDeleteMissingRow | ErrorAddExistingTable | ErrorDeleteMissingTable | ErrorUpdateMissingRow | ErrorChangeCodePage | ValidateProduct, /// Default value for patch transforms. PatchTransformDefault = ErrorAddExistingRow | ErrorDeleteMissingRow | ErrorAddExistingTable | ErrorDeleteMissingTable | ErrorUpdateMissingRow | ValidateProduct | ValidateUpdateVersion | ValidateNewEqualBaseVersion | ValidateUpgradeCode, } }