diff options
| author | Rob Mensching <rob@firegiant.com> | 2017-10-14 16:12:07 -0700 |
|---|---|---|
| committer | Rob Mensching <rob@firegiant.com> | 2017-10-14 16:12:07 -0700 |
| commit | dbde9e7104b907bbbaea17e21247d8cafc8b3a4c (patch) | |
| tree | 0f5fbbb6fe12c6b2e5e622a0e18ce4c5b4eb2b96 /src/WixToolset.Core.WindowsInstaller/Msi/Installer.cs | |
| parent | fbf986eb97f68396797a89fc7d40dec07b775440 (diff) | |
| download | wix-dbde9e7104b907bbbaea17e21247d8cafc8b3a4c.tar.gz wix-dbde9e7104b907bbbaea17e21247d8cafc8b3a4c.tar.bz2 wix-dbde9e7104b907bbbaea17e21247d8cafc8b3a4c.zip | |
Massive refactoring to introduce the concept of IBackend
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 | } | ||
