// 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.Globalization;
using System.Text;
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();
}
}
}
}