diff options
Diffstat (limited to 'src/WixToolset.Core.Native/Msi/SummaryInformation.cs')
-rw-r--r-- | src/WixToolset.Core.Native/Msi/SummaryInformation.cs | 243 |
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 | |||
3 | namespace 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 | } | ||