aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core.Native/Msi/Installer.cs
blob: 2bb410780034b5dc2c8c4a2e58f8a18d08575941 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// 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.

namespace WixToolset.Core.Native.Msi
{
    using System;
    using System.Diagnostics;
    using System.Text;

    /// <summary>
    /// A callback function that the installer calls for progress notification and error messages.
    /// </summary>
    /// <param name="context">Pointer to an application context.
    /// This parameter can be used for error checking.</param>
    /// <param name="messageType">Specifies a combination of one message box style,
    /// one message box icon type, one default button, and one installation message type.</param>
    /// <param name="message">Specifies the message text.</param>
    /// <returns>-1 for an error, 0 if no action was taken, 1 if OK, 3 to abort.</returns>
    public delegate int InstallUIHandler(IntPtr context, uint messageType, string message);

    /// <summary>
    /// Represents the Windows Installer, provides wrappers to
    /// create the top-level objects and access their methods.
    /// </summary>
    public static class Installer
    {
        /// <summary>
        /// Takes the path to a file and returns a 128-bit hash of that file.
        /// </summary>
        /// <param name="filePath">Path to file that is to be hashed.</param>
        /// <param name="options">The value in this column must be 0. This parameter is reserved for future use.</param>
        /// <param name="hash">Int array that receives the returned file hash information.</param>
        public static void GetFileHash(string filePath, int options, out int[] hash)
        {
            var hashInterop = new MSIFILEHASHINFO();
            hashInterop.FileHashInfoSize = 20;

            var error = MsiInterop.MsiGetFileHash(filePath, Convert.ToUInt32(options), hashInterop);
            if (0 != error)
            {
                throw new MsiException(error);
            }

            Debug.Assert(20 == hashInterop.FileHashInfoSize);

            hash = new int[4];
            hash[0] = hashInterop.Data0;
            hash[1] = hashInterop.Data1;
            hash[2] = hashInterop.Data2;
            hash[3] = hashInterop.Data3;
        }

        /// <summary>
        /// Returns the version string and language string in the format that the installer 
        /// expects to find them in the database.  If you just want version information, set 
        /// lpLangBuf and pcchLangBuf to zero. If you just want language information, set 
        /// lpVersionBuf and pcchVersionBuf to zero.
        /// </summary>
        /// <param name="filePath">Specifies the path to the file.</param>
        /// <param name="version">Returns the file version. Set to 0 for language information only.</param>
        /// <param name="language">Returns the file language. Set to 0 for version information only.</param>
        public static void GetFileVersion(string filePath, out string version, out string language)
        {
            var versionLength = 20;
            var languageLength = 20;
            var versionBuffer = new StringBuilder(versionLength);
            var languageBuffer = new StringBuilder(languageLength);

            var error = MsiInterop.MsiGetFileVersion(filePath, versionBuffer, ref versionLength, languageBuffer, ref languageLength);
            if (234 == error)
            {
                versionBuffer.EnsureCapacity(++versionLength);
                languageBuffer.EnsureCapacity(++languageLength);
                error = MsiInterop.MsiGetFileVersion(filePath, versionBuffer, ref versionLength, languageBuffer, ref languageLength);
            }
            else if (1006 == error)
            {
                // file has no version or language, so no error
                error = 0;
            }

            if (0 != error)
            {
                throw new MsiException(error);
            }

            version = versionBuffer.ToString();
            language = languageBuffer.ToString();
        }

        /// <summary>
        /// Enables an external user-interface handler.
        /// </summary>
        /// <param name="installUIHandler">Specifies a callback function.</param>
        /// <param name="messageFilter">Specifies which messages to handle using the external message handler.</param>
        /// <param name="context">Pointer to an application context that is passed to the callback function.</param>
        /// <returns>The return value is the previously set external handler, or null if there was no previously set handler.</returns>
        public static InstallUIHandler SetExternalUI(InstallUIHandler installUIHandler, int messageFilter, IntPtr context)
        {
            return MsiInterop.MsiSetExternalUI(installUIHandler, messageFilter, context);
        }

        /// <summary>
        /// Enables the installer's internal user interface.
        /// </summary>
        /// <param name="uiLevel">Specifies the level of complexity of the user interface.</param>
        /// <param name="hwnd">Pointer to a window. This window becomes the owner of any user interface created.</param>
        /// <returns>The previous user interface level is returned. If an invalid dwUILevel is passed, then INSTALLUILEVEL_NOCHANGE is returned.</returns>
        public static int SetInternalUI(int uiLevel, ref IntPtr hwnd)
        {
            return MsiInterop.MsiSetInternalUI(uiLevel, ref hwnd);
        }
    }
}