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