// 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.Mba.Core
{
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
///
/// Default implementation of .
///
public sealed class Engine : IEngine
{
private static readonly string normalizeVersionFormatString = "{0} must be less than or equal to " + UInt16.MaxValue;
private IBootstrapperEngine engine;
///
/// Creates a new instance of the container class.
///
/// The to contain.
internal Engine(IBootstrapperEngine engine)
{
this.engine = engine;
}
///
public int PackageCount
{
get
{
int count;
this.engine.GetPackageCount(out count);
return count;
}
}
///
public void Apply(IntPtr hwndParent)
{
this.engine.Apply(hwndParent);
}
///
public void CloseSplashScreen()
{
this.engine.CloseSplashScreen();
}
///
public int CompareVersions(string version1, string version2)
{
this.engine.CompareVersions(version1, version2, out var result);
return result;
}
///
public bool ContainsVariable(string name)
{
return BalUtil.BalVariableExistsFromEngine(this.engine, name);
}
///
public void Detect()
{
this.Detect(IntPtr.Zero);
}
///
public void Detect(IntPtr hwndParent)
{
this.engine.Detect(hwndParent);
}
///
public bool Elevate(IntPtr hwndParent)
{
int ret = this.engine.Elevate(hwndParent);
if (NativeMethods.S_OK == ret || NativeMethods.E_ALREADYINITIALIZED == ret)
{
return true;
}
else if (NativeMethods.E_CANCELLED == ret)
{
return false;
}
else
{
throw new Win32Exception(ret);
}
}
///
public string EscapeString(string input)
{
StrUtil.StrHandle handle = new StrUtil.StrHandle();
try
{
int ret = BalUtil.BalEscapeStringFromEngine(this.engine, input, ref handle);
if (ret != NativeMethods.S_OK)
{
throw new Win32Exception(ret);
}
return handle.ToUniString();
}
finally
{
handle.Dispose();
}
}
///
public bool EvaluateCondition(string condition)
{
bool value;
this.engine.EvaluateCondition(condition, out value);
return value;
}
///
public string FormatString(string format)
{
StrUtil.StrHandle handle = new StrUtil.StrHandle();
try
{
int ret = BalUtil.BalFormatStringFromEngine(this.engine, format, ref handle);
if (ret != NativeMethods.S_OK)
{
throw new Win32Exception(ret);
}
return handle.ToUniString();
}
finally
{
handle.Dispose();
}
}
///
public long GetVariableNumeric(string name)
{
int ret = this.engine.GetVariableNumeric(name, out long value);
if (NativeMethods.S_OK != ret)
{
throw new Win32Exception(ret);
}
return value;
}
///
public SecureString GetVariableSecureString(string name)
{
StrUtil.StrHandle handle = new StrUtil.StrHandle();
try
{
int ret = BalUtil.BalGetStringVariableFromEngine(this.engine, name, ref handle);
if (ret != NativeMethods.S_OK)
{
throw new Win32Exception(ret);
}
return handle.ToSecureString();
}
finally
{
handle.Dispose();
}
}
///
public string GetVariableString(string name)
{
StrUtil.StrHandle handle = new StrUtil.StrHandle();
try
{
int ret = BalUtil.BalGetStringVariableFromEngine(this.engine, name, ref handle);
if (ret != NativeMethods.S_OK)
{
throw new Win32Exception(ret);
}
return handle.ToUniString();
}
finally
{
handle.Dispose();
}
}
///
public string GetVariableVersion(string name)
{
StrUtil.StrHandle handle = new StrUtil.StrHandle();
try
{
int ret = BalUtil.BalGetVersionVariableFromEngine(this.engine, name, ref handle);
if (ret != NativeMethods.S_OK)
{
throw new Win32Exception(ret);
}
return handle.ToUniString();
}
finally
{
handle.Dispose();
}
}
///
public string GetRelatedBundleVariable(string bundleId, string name)
{
StrUtil.StrHandle handle = new StrUtil.StrHandle();
try
{
int ret = BalUtil.BalGetRelatedBundleVariableFromEngine(this.engine, bundleId, name, ref handle);
if (ret != NativeMethods.S_OK)
{
throw new Win32Exception(ret);
}
return handle.ToUniString();
}
finally
{
handle.Dispose();
}
}
///
public void LaunchApprovedExe(IntPtr hwndParent, string approvedExeForElevationId, string arguments)
{
this.LaunchApprovedExe(hwndParent, approvedExeForElevationId, arguments, 0);
}
///
public void LaunchApprovedExe(IntPtr hwndParent, string approvedExeForElevationId, string arguments, int waitForInputIdleTimeout)
{
this.engine.LaunchApprovedExe(hwndParent, approvedExeForElevationId, arguments, waitForInputIdleTimeout);
}
///
public void Log(LogLevel level, string message)
{
this.engine.Log(level, message);
}
///
public void Plan(LaunchAction action)
{
this.engine.Plan(action);
}
///
public void SetUpdate(string localSource, string downloadSource, long size, UpdateHashType hashType, string hash)
{
this.engine.SetUpdate(localSource, downloadSource, size, hashType, hash);
}
///
public void SetUpdateSource(string url)
{
this.engine.SetUpdateSource(url);
}
///
public void SetLocalSource(string packageOrContainerId, string payloadId, string path)
{
this.engine.SetLocalSource(packageOrContainerId, payloadId, path);
}
///
public void SetDownloadSource(string packageOrContainerId, string payloadId, string url, string user, string password)
{
this.engine.SetDownloadSource(packageOrContainerId, payloadId, url, user, password);
}
///
public void SetVariableNumeric(string name, long value)
{
this.engine.SetVariableNumeric(name, value);
}
///
public void SetVariableString(string name, SecureString value, bool formatted)
{
IntPtr pValue = Marshal.SecureStringToCoTaskMemUnicode(value);
try
{
this.engine.SetVariableString(name, pValue, formatted);
}
finally
{
Marshal.FreeCoTaskMem(pValue);
}
}
///
public void SetVariableString(string name, string value, bool formatted)
{
IntPtr pValue = Marshal.StringToCoTaskMemUni(value);
try
{
this.engine.SetVariableString(name, pValue, formatted);
}
finally
{
Marshal.FreeCoTaskMem(pValue);
}
}
///
public void SetVariableVersion(string name, string value)
{
IntPtr pValue = Marshal.StringToCoTaskMemUni(value);
try
{
this.engine.SetVariableVersion(name, pValue);
}
finally
{
Marshal.FreeCoTaskMem(pValue);
}
}
///
public int SendEmbeddedError(int errorCode, string message, int uiHint)
{
int result = 0;
this.engine.SendEmbeddedError(errorCode, message, uiHint, out result);
return result;
}
///
public int SendEmbeddedProgress(int progressPercentage, int overallPercentage)
{
int result = 0;
this.engine.SendEmbeddedProgress(progressPercentage, overallPercentage, out result);
return result;
}
///
public void Quit(int exitCode)
{
this.engine.Quit(exitCode);
}
///
/// Utility method for converting a into a .
///
///
///
public static long VersionToLong(Version version)
{
// In Windows, each version component has a max value of 65535,
// so we truncate the version before shifting it, which will overflow if invalid.
long major = (long)(ushort)version.Major << 48;
long minor = (long)(ushort)version.Minor << 32;
long build = (long)(ushort)version.Build << 16;
long revision = (long)(ushort)version.Revision;
return major | minor | build | revision;
}
///
/// Utility method for converting a into a .
///
///
///
public static Version LongToVersion(long version)
{
int major = (int)((version & ((long)0xffff << 48)) >> 48);
int minor = (int)((version & ((long)0xffff << 32)) >> 32);
int build = (int)((version & ((long)0xffff << 16)) >> 16);
int revision = (int)(version & 0xffff);
return new Version(major, minor, build, revision);
}
///
/// Verifies that Version can be represented in a .
/// If the Build or Revision fields are undefined, they are set to zero.
///
public static Version NormalizeVersion(Version version)
{
if (version == null)
{
throw new ArgumentNullException("version");
}
int major = version.Major;
int minor = version.Minor;
int build = version.Build;
int revision = version.Revision;
if (major > UInt16.MaxValue)
{
throw new ArgumentOutOfRangeException("version", String.Format(normalizeVersionFormatString, "Major"));
}
if (minor > UInt16.MaxValue)
{
throw new ArgumentOutOfRangeException("version", String.Format(normalizeVersionFormatString, "Minor"));
}
if (build > UInt16.MaxValue)
{
throw new ArgumentOutOfRangeException("version", String.Format(normalizeVersionFormatString, "Build"));
}
if (build == -1)
{
build = 0;
}
if (revision > UInt16.MaxValue)
{
throw new ArgumentOutOfRangeException("version", String.Format(normalizeVersionFormatString, "Revision"));
}
if (revision == -1)
{
revision = 0;
}
return new Version(major, minor, build, revision);
}
}
}