aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core.Native/Msi/SummaryInformation.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Core.Native/Msi/SummaryInformation.cs')
-rw-r--r--src/WixToolset.Core.Native/Msi/SummaryInformation.cs243
1 files changed, 243 insertions, 0 deletions
diff --git a/src/WixToolset.Core.Native/Msi/SummaryInformation.cs b/src/WixToolset.Core.Native/Msi/SummaryInformation.cs
new file mode 100644
index 00000000..a7ba5717
--- /dev/null
+++ b/src/WixToolset.Core.Native/Msi/SummaryInformation.cs
@@ -0,0 +1,243 @@
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
3namespace WixToolset.Core.Native.Msi
4{
5 using System;
6 using System.Globalization;
7 using System.Text;
8 using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
9
10 /// <summary>
11 /// Summary information for the MSI files.
12 /// </summary>
13 public sealed class SummaryInformation : MsiHandle
14 {
15 /// <summary>
16 /// Summary information properties for transforms.
17 /// </summary>
18 public enum Transform
19 {
20 /// <summary>PID_CODEPAGE = code page for the summary information stream</summary>
21 CodePage = 1,
22
23 /// <summary>PID_TITLE = typically just "Transform"</summary>
24 Title = 2,
25
26 /// <summary>PID_SUBJECT = original subject of target</summary>
27 TargetSubject = 3,
28
29 /// <summary>PID_AUTHOR = original manufacturer of target</summary>
30 TargetManufacturer = 4,
31
32 /// <summary>PID_KEYWORDS = keywords for the transform, typically including at least "Installer"</summary>
33 Keywords = 5,
34
35 /// <summary>PID_COMMENTS = describes what this package does</summary>
36 Comments = 6,
37
38 /// <summary>PID_TEMPLATE = target platform;language</summary>
39 TargetPlatformAndLanguage = 7,
40
41 /// <summary>PID_LASTAUTHOR = updated platform;language</summary>
42 UpdatedPlatformAndLanguage = 8,
43
44 /// <summary>PID_REVNUMBER = {productcode}version;{newproductcode}newversion;upgradecode</summary>
45 ProductCodes = 9,
46
47 /// <summary>PID_LASTPRINTED should be null for transforms</summary>
48 Reserved11 = 11,
49
50 ///.<summary>PID_CREATE_DTM = the timestamp when the transform was created</summary>
51 CreationTime = 12,
52
53 /// <summary>PID_PAGECOUNT = minimum installer version</summary>
54 InstallerRequirement = 14,
55
56 /// <summary>PID_CHARCOUNT = validation and error flags</summary>
57 ValidationFlags = 16,
58
59 /// <summary>PID_APPNAME = the application that created the transform</summary>
60 CreatingApplication = 18,
61
62 /// <summary>PID_SECURITY = whether read-only is enforced; should always be 4 for transforms</summary>
63 Security = 19,
64 }
65
66 /// <summary>
67 /// Summary information properties for patches.
68 /// </summary>
69 public enum Patch
70 {
71 /// <summary>PID_CODEPAGE = code page of the summary information stream</summary>
72 CodePage = 1,
73
74 /// <summary>PID_TITLE = a brief description of the package type</summary>
75 Title = 2,
76
77 /// <summary>PID_SUBJECT = package name</summary>
78 PackageName = 3,
79
80 /// <summary>PID_AUTHOR = manufacturer of the patch package</summary>
81 Manufacturer = 4,
82
83 /// <summary>PID_KEYWORDS = alternate sources for the patch package</summary>
84 Sources = 5,
85
86 /// <summary>PID_COMMENTS = general purpose of the patch package</summary>
87 Comments = 6,
88
89 /// <summary>PID_TEMPLATE = semicolon delimited list of ProductCodes</summary>
90 ProductCodes = 7,
91
92 /// <summary>PID_LASTAUTHOR = semicolon delimited list of transform names</summary>
93 TransformNames = 8,
94
95 /// <summary>PID_REVNUMBER = GUID patch code</summary>
96 PatchCode = 9,
97
98 /// <summary>PID_LASTPRINTED should be null for patches</summary>
99 Reserved11 = 11,
100
101 /// <summary>PID_PAGECOUNT should be null for patches</summary>
102 Reserved14 = 14,
103
104 /// <summary>PID_WORDCOUNT = minimum installer version</summary>
105 InstallerRequirement = 15,
106
107 /// <summary>PID_CHARCOUNT should be null for patches</summary>
108 Reserved16 = 16,
109
110 /// <summary>PID_SECURITY = read-only attribute of the patch package</summary>
111 Security = 19,
112 }
113
114 /// <summary>
115 /// Summary information values for the InstallerRequirement property.
116 /// </summary>
117 public enum InstallerRequirement
118 {
119 /// <summary>Any version of the installer will do</summary>
120 Version10 = 1,
121
122 /// <summary>At least 1.2</summary>
123 Version12 = 2,
124
125 /// <summary>At least 2.0</summary>
126 Version20 = 3,
127
128 /// <summary>At least 3.0</summary>
129 Version30 = 4,
130
131 /// <summary>At least 3.1</summary>
132 Version31 = 5,
133 }
134
135 /// <summary>
136 /// Instantiate a new SummaryInformation class from an open database.
137 /// </summary>
138 /// <param name="db">Database to retrieve summary information from.</param>
139 public SummaryInformation(Database db)
140 {
141 if (null == db)
142 {
143 throw new ArgumentNullException("db");
144 }
145
146 uint handle = 0;
147 var error = MsiInterop.MsiGetSummaryInformation(db.Handle, null, 0, ref handle);
148 if (0 != error)
149 {
150 throw new MsiException(error);
151 }
152 this.Handle = handle;
153 }
154
155 /// <summary>
156 /// Instantiate a new SummaryInformation class from a database file.
157 /// </summary>
158 /// <param name="databaseFile">The database file.</param>
159 public SummaryInformation(string databaseFile)
160 {
161 if (null == databaseFile)
162 {
163 throw new ArgumentNullException("databaseFile");
164 }
165
166 uint handle = 0;
167 var error = MsiInterop.MsiGetSummaryInformation(0, databaseFile, 0, ref handle);
168 if (0 != error)
169 {
170 throw new MsiException(error);
171 }
172 this.Handle = handle;
173 }
174
175 /// <summary>
176 /// Gets a summary information property.
177 /// </summary>
178 /// <param name="index">Index of the summary information property.</param>
179 /// <returns>The summary information property.</returns>
180 public string GetProperty(int index)
181 {
182 var bufSize = 64;
183 var stringValue = new StringBuilder(bufSize);
184
185 FILETIME timeValue;
186 timeValue.dwHighDateTime = 0;
187 timeValue.dwLowDateTime = 0;
188
189 var error = MsiInterop.MsiSummaryInfoGetProperty(this.Handle, index, out var dataType, out var intValue, ref timeValue, stringValue, ref bufSize);
190 if (234 == error)
191 {
192 stringValue.EnsureCapacity(++bufSize);
193 error = MsiInterop.MsiSummaryInfoGetProperty(this.Handle, index, out dataType, out intValue, ref timeValue, stringValue, ref bufSize);
194 }
195
196 if (0 != error)
197 {
198 throw new MsiException(error);
199 }
200
201 switch ((VT)dataType)
202 {
203 case VT.EMPTY:
204 return String.Empty;
205 case VT.LPSTR:
206 return stringValue.ToString();
207 case VT.I2:
208 case VT.I4:
209 return Convert.ToString(intValue, CultureInfo.InvariantCulture);
210 case VT.FILETIME:
211 var longFileTime = (((long)timeValue.dwHighDateTime) << 32) | unchecked((uint)timeValue.dwLowDateTime);
212 var dateTime = DateTime.FromFileTime(longFileTime);
213 return dateTime.ToString("yyyy/MM/dd HH:mm:ss", CultureInfo.InvariantCulture);
214 default:
215 throw new InvalidOperationException();
216 }
217 }
218
219 /// <summary>
220 /// Variant types in the summary information table.
221 /// </summary>
222 private enum VT : uint
223 {
224 /// <summary>Variant has not been assigned.</summary>
225 EMPTY = 0,
226
227 /// <summary>Null variant type.</summary>
228 NULL = 1,
229
230 /// <summary>16-bit integer variant type.</summary>
231 I2 = 2,
232
233 /// <summary>32-bit integer variant type.</summary>
234 I4 = 3,
235
236 /// <summary>String variant type.</summary>
237 LPSTR = 30,
238
239 /// <summary>Date time (FILETIME, converted to Variant time) variant type.</summary>
240 FILETIME = 64,
241 }
242 }
243}