diff options
Diffstat (limited to 'src/WixToolset.Core.WindowsInstaller/Msi/Installer.cs')
-rw-r--r-- | src/WixToolset.Core.WindowsInstaller/Msi/Installer.cs | 363 |
1 files changed, 363 insertions, 0 deletions
diff --git a/src/WixToolset.Core.WindowsInstaller/Msi/Installer.cs b/src/WixToolset.Core.WindowsInstaller/Msi/Installer.cs new file mode 100644 index 00000000..f8bce602 --- /dev/null +++ b/src/WixToolset.Core.WindowsInstaller/Msi/Installer.cs | |||
@@ -0,0 +1,363 @@ | |||
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.Diagnostics; | ||
7 | using System.Text; | ||
8 | using WixToolset.Core.Native; | ||
9 | |||
10 | /// <summary> | ||
11 | /// Windows Installer message types. | ||
12 | /// </summary> | ||
13 | [Flags] | ||
14 | internal enum InstallMessage | ||
15 | { | ||
16 | /// <summary> | ||
17 | /// Premature termination, possibly fatal out of memory. | ||
18 | /// </summary> | ||
19 | FatalExit = 0x00000000, | ||
20 | |||
21 | /// <summary> | ||
22 | /// Formatted error message, [1] is message number in Error table. | ||
23 | /// </summary> | ||
24 | Error = 0x01000000, | ||
25 | |||
26 | /// <summary> | ||
27 | /// Formatted warning message, [1] is message number in Error table. | ||
28 | /// </summary> | ||
29 | Warning = 0x02000000, | ||
30 | |||
31 | /// <summary> | ||
32 | /// User request message, [1] is message number in Error table. | ||
33 | /// </summary> | ||
34 | User = 0x03000000, | ||
35 | |||
36 | /// <summary> | ||
37 | /// Informative message for log, not to be displayed. | ||
38 | /// </summary> | ||
39 | Info = 0x04000000, | ||
40 | |||
41 | /// <summary> | ||
42 | /// List of files in use that need to be replaced. | ||
43 | /// </summary> | ||
44 | FilesInUse = 0x05000000, | ||
45 | |||
46 | /// <summary> | ||
47 | /// Request to determine a valid source location. | ||
48 | /// </summary> | ||
49 | ResolveSource = 0x06000000, | ||
50 | |||
51 | /// <summary> | ||
52 | /// Insufficient disk space message. | ||
53 | /// </summary> | ||
54 | OutOfDiskSpace = 0x07000000, | ||
55 | |||
56 | /// <summary> | ||
57 | /// Progress: start of action, [1] action name, [2] description, [3] template for ACTIONDATA messages. | ||
58 | /// </summary> | ||
59 | ActionStart = 0x08000000, | ||
60 | |||
61 | /// <summary> | ||
62 | /// Action data. Record fields correspond to the template of ACTIONSTART message. | ||
63 | /// </summary> | ||
64 | ActionData = 0x09000000, | ||
65 | |||
66 | /// <summary> | ||
67 | /// Progress bar information. See the description of record fields below. | ||
68 | /// </summary> | ||
69 | Progress = 0x0A000000, | ||
70 | |||
71 | /// <summary> | ||
72 | /// To enable the Cancel button set [1] to 2 and [2] to 1. To disable the Cancel button set [1] to 2 and [2] to 0. | ||
73 | /// </summary> | ||
74 | CommonData = 0x0B000000, | ||
75 | |||
76 | /// <summary> | ||
77 | /// Sent prior to UI initialization, no string data. | ||
78 | /// </summary> | ||
79 | Initilize = 0x0C000000, | ||
80 | |||
81 | /// <summary> | ||
82 | /// Sent after UI termination, no string data. | ||
83 | /// </summary> | ||
84 | Terminate = 0x0D000000, | ||
85 | |||
86 | /// <summary> | ||
87 | /// Sent prior to display or authored dialog or wizard. | ||
88 | /// </summary> | ||
89 | ShowDialog = 0x0E000000 | ||
90 | } | ||
91 | |||
92 | /// <summary> | ||
93 | /// Windows Installer log modes. | ||
94 | /// </summary> | ||
95 | [Flags] | ||
96 | internal enum InstallLogModes | ||
97 | { | ||
98 | /// <summary> | ||
99 | /// Premature termination of installation. | ||
100 | /// </summary> | ||
101 | FatalExit = (1 << ((int)InstallMessage.FatalExit >> 24)), | ||
102 | |||
103 | /// <summary> | ||
104 | /// The error messages are logged. | ||
105 | /// </summary> | ||
106 | Error = (1 << ((int)InstallMessage.Error >> 24)), | ||
107 | |||
108 | /// <summary> | ||
109 | /// The warning messages are logged. | ||
110 | /// </summary> | ||
111 | Warning = (1 << ((int)InstallMessage.Warning >> 24)), | ||
112 | |||
113 | /// <summary> | ||
114 | /// The user requests are logged. | ||
115 | /// </summary> | ||
116 | User = (1 << ((int)InstallMessage.User >> 24)), | ||
117 | |||
118 | /// <summary> | ||
119 | /// The status messages that are not displayed are logged. | ||
120 | /// </summary> | ||
121 | Info = (1 << ((int)InstallMessage.Info >> 24)), | ||
122 | |||
123 | /// <summary> | ||
124 | /// Request to determine a valid source location. | ||
125 | /// </summary> | ||
126 | ResolveSource = (1 << ((int)InstallMessage.ResolveSource >> 24)), | ||
127 | |||
128 | /// <summary> | ||
129 | /// The was insufficient disk space. | ||
130 | /// </summary> | ||
131 | OutOfDiskSpace = (1 << ((int)InstallMessage.OutOfDiskSpace >> 24)), | ||
132 | |||
133 | /// <summary> | ||
134 | /// The start of new installation actions are logged. | ||
135 | /// </summary> | ||
136 | ActionStart = (1 << ((int)InstallMessage.ActionStart >> 24)), | ||
137 | |||
138 | /// <summary> | ||
139 | /// The data record with the installation action is logged. | ||
140 | /// </summary> | ||
141 | ActionData = (1 << ((int)InstallMessage.ActionData >> 24)), | ||
142 | |||
143 | /// <summary> | ||
144 | /// The parameters for user-interface initialization are logged. | ||
145 | /// </summary> | ||
146 | CommonData = (1 << ((int)InstallMessage.CommonData >> 24)), | ||
147 | |||
148 | /// <summary> | ||
149 | /// Logs the property values at termination. | ||
150 | /// </summary> | ||
151 | PropertyDump = (1 << ((int)InstallMessage.Progress >> 24)), | ||
152 | |||
153 | /// <summary> | ||
154 | /// Sends large amounts of information to a log file not generally useful to users. | ||
155 | /// May be used for technical support. | ||
156 | /// </summary> | ||
157 | Verbose = (1 << ((int)InstallMessage.Initilize >> 24)), | ||
158 | |||
159 | /// <summary> | ||
160 | /// Sends extra debugging information, such as handle creation information, to the log file. | ||
161 | /// </summary> | ||
162 | ExtraDebug = (1 << ((int)InstallMessage.Terminate >> 24)), | ||
163 | |||
164 | /// <summary> | ||
165 | /// Progress bar information. This message includes information on units so far and total number of units. | ||
166 | /// See MsiProcessMessage for an explanation of the message format. | ||
167 | /// This message is only sent to an external user interface and is not logged. | ||
168 | /// </summary> | ||
169 | Progress = (1 << ((int)InstallMessage.Progress >> 24)), | ||
170 | |||
171 | /// <summary> | ||
172 | /// If this is not a quiet installation, then the basic UI has been initialized. | ||
173 | /// If this is a full UI installation, the full UI is not yet initialized. | ||
174 | /// This message is only sent to an external user interface and is not logged. | ||
175 | /// </summary> | ||
176 | Initialize = (1 << ((int)InstallMessage.Initilize >> 24)), | ||
177 | |||
178 | /// <summary> | ||
179 | /// If a full UI is being used, the full UI has ended. | ||
180 | /// If this is not a quiet installation, the basic UI has not yet ended. | ||
181 | /// This message is only sent to an external user interface and is not logged. | ||
182 | /// </summary> | ||
183 | Terminate = (1 << ((int)InstallMessage.Terminate >> 24)), | ||
184 | |||
185 | /// <summary> | ||
186 | /// Sent prior to display of the full UI dialog. | ||
187 | /// This message is only sent to an external user interface and is not logged. | ||
188 | /// </summary> | ||
189 | ShowDialog = (1 << ((int)InstallMessage.ShowDialog >> 24)), | ||
190 | |||
191 | /// <summary> | ||
192 | /// Files in use information. When this message is received, a FilesInUse Dialog should be displayed. | ||
193 | /// </summary> | ||
194 | FilesInUse = (1 << ((int)InstallMessage.FilesInUse >> 24)) | ||
195 | } | ||
196 | |||
197 | /// <summary> | ||
198 | /// Windows Installer UI levels. | ||
199 | /// </summary> | ||
200 | [Flags] | ||
201 | internal enum InstallUILevels | ||
202 | { | ||
203 | /// <summary> | ||
204 | /// No change in the UI level. However, if phWnd is not Null, the parent window can change. | ||
205 | /// </summary> | ||
206 | NoChange = 0, | ||
207 | |||
208 | /// <summary> | ||
209 | /// The installer chooses an appropriate user interface level. | ||
210 | /// </summary> | ||
211 | Default = 1, | ||
212 | |||
213 | /// <summary> | ||
214 | /// Completely silent installation. | ||
215 | /// </summary> | ||
216 | None = 2, | ||
217 | |||
218 | /// <summary> | ||
219 | /// Simple progress and error handling. | ||
220 | /// </summary> | ||
221 | Basic = 3, | ||
222 | |||
223 | /// <summary> | ||
224 | /// Authored user interface with wizard dialog boxes suppressed. | ||
225 | /// </summary> | ||
226 | Reduced = 4, | ||
227 | |||
228 | /// <summary> | ||
229 | /// Authored user interface with wizards, progress, and errors. | ||
230 | /// </summary> | ||
231 | Full = 5, | ||
232 | |||
233 | /// <summary> | ||
234 | /// If combined with the Basic value, the installer shows simple progress dialog boxes but | ||
235 | /// does not display a Cancel button on the dialog. This prevents users from canceling the install. | ||
236 | /// Available with Windows Installer version 2.0. | ||
237 | /// </summary> | ||
238 | HideCancel = 0x20, | ||
239 | |||
240 | /// <summary> | ||
241 | /// If combined with the Basic value, the installer shows simple progress | ||
242 | /// dialog boxes but does not display any modal dialog boxes or error dialog boxes. | ||
243 | /// </summary> | ||
244 | ProgressOnly = 0x40, | ||
245 | |||
246 | /// <summary> | ||
247 | /// If combined with any above value, the installer displays a modal dialog | ||
248 | /// box at the end of a successful installation or if there has been an error. | ||
249 | /// No dialog box is displayed if the user cancels. | ||
250 | /// </summary> | ||
251 | EndDialog = 0x80, | ||
252 | |||
253 | /// <summary> | ||
254 | /// If this value is combined with the None value, the installer displays only the dialog | ||
255 | /// boxes used for source resolution. No other dialog boxes are shown. This value has no | ||
256 | /// effect if the UI level is not INSTALLUILEVEL_NONE. It is used with an external user | ||
257 | /// interface designed to handle all of the UI except for source resolution. In this case, | ||
258 | /// the installer handles source resolution. This value is only available with Windows Installer 2.0 and later. | ||
259 | /// </summary> | ||
260 | SourceResOnly = 0x100 | ||
261 | } | ||
262 | |||
263 | /// <summary> | ||
264 | /// Represents the Windows Installer, provides wrappers to | ||
265 | /// create the top-level objects and access their methods. | ||
266 | /// </summary> | ||
267 | internal sealed class Installer | ||
268 | { | ||
269 | /// <summary> | ||
270 | /// Protect the constructor. | ||
271 | /// </summary> | ||
272 | private Installer() | ||
273 | { | ||
274 | } | ||
275 | |||
276 | /// <summary> | ||
277 | /// Takes the path to a file and returns a 128-bit hash of that file. | ||
278 | /// </summary> | ||
279 | /// <param name="filePath">Path to file that is to be hashed.</param> | ||
280 | /// <param name="options">The value in this column must be 0. This parameter is reserved for future use.</param> | ||
281 | /// <param name="hash">Int array that receives the returned file hash information.</param> | ||
282 | internal static void GetFileHash(string filePath, int options, out int[] hash) | ||
283 | { | ||
284 | MsiInterop.MSIFILEHASHINFO hashInterop = new MsiInterop.MSIFILEHASHINFO(); | ||
285 | hashInterop.FileHashInfoSize = 20; | ||
286 | |||
287 | int error = MsiInterop.MsiGetFileHash(filePath, Convert.ToUInt32(options), hashInterop); | ||
288 | if (0 != error) | ||
289 | { | ||
290 | throw new MsiException(error); | ||
291 | } | ||
292 | |||
293 | Debug.Assert(20 == hashInterop.FileHashInfoSize); | ||
294 | |||
295 | hash = new int[4]; | ||
296 | hash[0] = hashInterop.Data0; | ||
297 | hash[1] = hashInterop.Data1; | ||
298 | hash[2] = hashInterop.Data2; | ||
299 | hash[3] = hashInterop.Data3; | ||
300 | } | ||
301 | |||
302 | /// <summary> | ||
303 | /// Returns the version string and language string in the format that the installer | ||
304 | /// expects to find them in the database. If you just want version information, set | ||
305 | /// lpLangBuf and pcchLangBuf to zero. If you just want language information, set | ||
306 | /// lpVersionBuf and pcchVersionBuf to zero. | ||
307 | /// </summary> | ||
308 | /// <param name="filePath">Specifies the path to the file.</param> | ||
309 | /// <param name="version">Returns the file version. Set to 0 for language information only.</param> | ||
310 | /// <param name="language">Returns the file language. Set to 0 for version information only.</param> | ||
311 | internal static void GetFileVersion(string filePath, out string version, out string language) | ||
312 | { | ||
313 | int versionLength = 20; | ||
314 | int languageLength = 20; | ||
315 | StringBuilder versionBuffer = new StringBuilder(versionLength); | ||
316 | StringBuilder languageBuffer = new StringBuilder(languageLength); | ||
317 | |||
318 | int error = MsiInterop.MsiGetFileVersion(filePath, versionBuffer, ref versionLength, languageBuffer, ref languageLength); | ||
319 | if (234 == error) | ||
320 | { | ||
321 | versionBuffer.EnsureCapacity(++versionLength); | ||
322 | languageBuffer.EnsureCapacity(++languageLength); | ||
323 | error = MsiInterop.MsiGetFileVersion(filePath, versionBuffer, ref versionLength, languageBuffer, ref languageLength); | ||
324 | } | ||
325 | else if (1006 == error) | ||
326 | { | ||
327 | // file has no version or language, so no error | ||
328 | error = 0; | ||
329 | } | ||
330 | |||
331 | if (0 != error) | ||
332 | { | ||
333 | throw new MsiException(error); | ||
334 | } | ||
335 | |||
336 | version = versionBuffer.ToString(); | ||
337 | language = languageBuffer.ToString(); | ||
338 | } | ||
339 | |||
340 | /// <summary> | ||
341 | /// Enables an external user-interface handler. | ||
342 | /// </summary> | ||
343 | /// <param name="installUIHandler">Specifies a callback function.</param> | ||
344 | /// <param name="messageFilter">Specifies which messages to handle using the external message handler.</param> | ||
345 | /// <param name="context">Pointer to an application context that is passed to the callback function.</param> | ||
346 | /// <returns>The return value is the previously set external handler, or null if there was no previously set handler.</returns> | ||
347 | internal static InstallUIHandler SetExternalUI(InstallUIHandler installUIHandler, int messageFilter, IntPtr context) | ||
348 | { | ||
349 | return MsiInterop.MsiSetExternalUI(installUIHandler, messageFilter, context); | ||
350 | } | ||
351 | |||
352 | /// <summary> | ||
353 | /// Enables the installer's internal user interface. | ||
354 | /// </summary> | ||
355 | /// <param name="uiLevel">Specifies the level of complexity of the user interface.</param> | ||
356 | /// <param name="hwnd">Pointer to a window. This window becomes the owner of any user interface created.</param> | ||
357 | /// <returns>The previous user interface level is returned. If an invalid dwUILevel is passed, then INSTALLUILEVEL_NOCHANGE is returned.</returns> | ||
358 | internal static int SetInternalUI(int uiLevel, ref IntPtr hwnd) | ||
359 | { | ||
360 | return MsiInterop.MsiSetInternalUI(uiLevel, ref hwnd); | ||
361 | } | ||
362 | } | ||
363 | } | ||