diff --git a/packages/accounts-base/package.js b/packages/accounts-base/package.js index 183df2d01e..139d945466 100644 --- a/packages/accounts-base/package.js +++ b/packages/accounts-base/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "A user account system", - version: "1.1.4-winr.2" + version: "1.1.4-winr.3" }); Package.onUse(function (api) { diff --git a/packages/blaze/package.js b/packages/blaze/package.js index 2cf2f68288..45e3608ca4 100644 --- a/packages/blaze/package.js +++ b/packages/blaze/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Meteor Reactive Templating library", - version: '2.0.5-winr.3' + version: '2.0.5-winr.4' }); Package.onUse(function (api) { diff --git a/packages/boilerplate-generator/package.js b/packages/boilerplate-generator/package.js index 2b88076166..aa2980f488 100644 --- a/packages/boilerplate-generator/package.js +++ b/packages/boilerplate-generator/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Generates the boilerplate html from program's manifest", - version: '1.0.3-winr.2' + version: '1.0.3-winr.3' }); Package.onUse(function (api) { diff --git a/packages/email/package.js b/packages/email/package.js index 66c019af10..6d249510fa 100644 --- a/packages/email/package.js +++ b/packages/email/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Send email messages", - version: "1.0.6-winr.3" + version: "1.0.6-winr.4" }); Npm.depends({ diff --git a/packages/launch-screen/package.js b/packages/launch-screen/package.js index cd6b9e2ebd..07b22de509 100644 --- a/packages/launch-screen/package.js +++ b/packages/launch-screen/package.js @@ -6,7 +6,7 @@ Package.describe({ // between such packages and the build tool. name: 'launch-screen', summary: 'Default and customizable launch screen on mobile.', - version: '1.0.1-winr.3' + version: '1.0.1-winr.4' }); Cordova.depends({ diff --git a/packages/logging/package.js b/packages/logging/package.js index d1796318e2..9a02e6c8ad 100644 --- a/packages/logging/package.js +++ b/packages/logging/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Logging facility.", - version: '1.0.6-winr.2' + version: '1.0.6-winr.3' }); Npm.depends({ diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index 57e3811bf1..ad1dc6c7dd 100644 --- a/packages/meteor-tool/package.js +++ b/packages/meteor-tool/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "The Meteor command-line tool", - version: '1.1.0-winr.8' + version: '1.1.0-winr.9' }); Package.includeTool(); diff --git a/packages/meteor/package.js b/packages/meteor/package.js index b8c789a9f7..413169b540 100644 --- a/packages/meteor/package.js +++ b/packages/meteor/package.js @@ -2,7 +2,7 @@ Package.describe({ summary: "Core Meteor environment", - version: '1.1.5-winr.5' + version: '1.1.5-winr.6' }); Package.registerBuildPlugin({ diff --git a/packages/mobile-status-bar/package.js b/packages/mobile-status-bar/package.js index a9024eb15d..a68125f9fd 100644 --- a/packages/mobile-status-bar/package.js +++ b/packages/mobile-status-bar/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Good defaults for the mobile status bar", - version: "1.0.3-winr.2" + version: "1.0.3-winr.3" }); Package.onUse(function(api) { diff --git a/packages/mongo/package.js b/packages/mongo/package.js index 52820beeae..1657d5a0e4 100644 --- a/packages/mongo/package.js +++ b/packages/mongo/package.js @@ -9,7 +9,7 @@ Package.describe({ summary: "Adaptor for using MongoDB and Minimongo over DDP", - version: '1.0.12-winr.4' + version: '1.0.12-winr.5' }); Npm.depends({ diff --git a/packages/oauth/package.js b/packages/oauth/package.js index ed943d2c92..4a8eba2836 100644 --- a/packages/oauth/package.js +++ b/packages/oauth/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Common code for OAuth-based services", - version: "1.1.4-winr.2" + version: "1.1.4-winr.3" }); Package.onUse(function (api) { diff --git a/packages/reactive-dict/package.js b/packages/reactive-dict/package.js index 1653ac77aa..58b15fab70 100644 --- a/packages/reactive-dict/package.js +++ b/packages/reactive-dict/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Reactive dictionary", - version: '1.0.6-winr.2' + version: '1.0.6-winr.3' }); Package.onUse(function (api) { diff --git a/packages/session/package.js b/packages/session/package.js index 846f4d28a9..edd4bf6d93 100644 --- a/packages/session/package.js +++ b/packages/session/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Session variable", - version: '1.0.6-winr.2' + version: '1.0.6-winr.3' }); Package.onUse(function (api) { diff --git a/packages/spacebars-compiler/package.js b/packages/spacebars-compiler/package.js index 639dfe3f0a..c5bc679ff9 100644 --- a/packages/spacebars-compiler/package.js +++ b/packages/spacebars-compiler/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Compiler for Spacebars template language", - version: '1.0.5-winr.2' + version: '1.0.5-winr.3' }); Package.onUse(function (api) { diff --git a/scripts/admin/meteor-release-experimental.json b/scripts/admin/meteor-release-experimental.json index ce24053b1d..1080b25e5d 100644 --- a/scripts/admin/meteor-release-experimental.json +++ b/scripts/admin/meteor-release-experimental.json @@ -1,6 +1,6 @@ { "track": "WINDOWS-PREVIEW", - "version": "0.1.7", + "version": "0.1.8", "recommended": false, "official": false, "description": "Preview of Meteor on Windows." diff --git a/scripts/windows/InstallMeteor.cs b/scripts/windows/InstallMeteor.cs deleted file mode 100644 index 208aea9395..0000000000 --- a/scripts/windows/InstallMeteor.cs +++ /dev/null @@ -1,558 +0,0 @@ -// Executable to launch meteor after bootstrapping the local warehouse -// -// Copyright 2013 - 2014 Stephen Darnell - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.IO.Compression; -using System.Net; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Text.RegularExpressions; -using System.Text; -using System.Threading; -using Microsoft.Win32.SafeHandles; - -[assembly: AssemblyTitle("Windows Meteor installer")] -[assembly: AssemblyDescription("Downloads the Meteor bootstrap package installs it")] -[assembly: AssemblyCompany("Meteor Development Group")] -[assembly: AssemblyProduct("Meteor")] -[assembly: AssemblyCopyright("Copyright 2014 Meteor Development Group")] -[assembly: AssemblyVersion("0.1.0.0")] -[assembly: AssemblyFileVersion("0.1.0.0")] - -namespace LaunchMeteor -{ - class Program - { - private const string BOOTSTRAP_FILE = "meteor-bootstrap-os.windows.x86_32.tar.gz"; - private const string BOOTSTRAP_URL = "https://s3.amazonaws.com/com.meteor.static/packages-bootstrap/__METEOR_RELEASE__/" + BOOTSTRAP_FILE; - - private const string METEOR_WAREHOUSE_DIR = "METEOR_WAREHOUSE_DIR"; - - private static string bootstrapFile = null; - private static bool looksLikeNewConsole = false; - private static int consoleWindowWidth = 80; - - private static void InitialiseConsoleInfo() - { - // Try/catch needed when not connected to a console - try - { - looksLikeNewConsole = Console.CursorLeft == 0 && Console.CursorTop == 0; - consoleWindowWidth = Console.WindowWidth; - } catch {} - } - - static void Main(string[] args) - { - InitialiseConsoleInfo(); - - // Avoid console vanishing without warning if invoked from a non-console app - AppDomain.CurrentDomain.UnhandledException += (sender, handlerArgs) => - { - Console.WriteLine("Unexpected exception: {0}", handlerArgs.ExceptionObject); - Exit(1); - }; - - if (args.Length == 1 && args[0] == "--downloaded") - { - bootstrapFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, BOOTSTRAP_FILE); - args = new string[0]; - } - - var home = Environment.GetEnvironmentVariable("LOCALAPPDATA") ?? - Environment.GetEnvironmentVariable("APPDATA"); - var warehouse = Path.Combine(home, ".meteor"); - Environment.SetEnvironmentVariable(METEOR_WAREHOUSE_DIR, warehouse); - - // XXX will this overwrite if Meteor is already installed? - // we would like it to - BootstrapWarehouse(warehouse); - Console.WriteLine("To run Meteor, open a new Command Prompt and type 'meteor'"); - Exit(1); - } - - #region Executing child processes - - private static void Exec(string command, string extra, string[] args) - { - if (extra != null) - { - var list = new List(args); - list.Insert(0, extra); - args = list.ToArray(); - } - string commandLine = string.Join(" ", Array.ConvertAll(args, QuoteArg)); - if (!File.Exists(command)) - { - Console.WriteLine("Unable to find executable for command:"); - Console.WriteLine(" {0} {1}", command, commandLine); - Exit(1); - } - var child = Process.Start(new ProcessStartInfo(command, commandLine) { UseShellExecute = false }); - child.WaitForExit(); - Exit(child.ExitCode); - } - - private static string QuoteArg(string unquoted) - { - if (unquoted.Length > 0 && unquoted.IndexOfAny(" \t\n\v\"".ToCharArray()) == -1) - return unquoted; - var result = new StringBuilder("\""); - int slashes = 0; - foreach (var ch in unquoted) - { - if (ch == '"') // Double up any slashes and escape the quote - { - while (slashes-- >= 0) result.Append('\\'); - } - result.Append(ch); - slashes = (ch == '\\') ? slashes + 1 : 0; - } - return result.Append('"').ToString(); - } - - public static void Exit(int exitCode) - { - if (looksLikeNewConsole) - { - Console.WriteLine("\nPlease press any key to exit."); - Console.ReadKey(true); - } - Environment.Exit(exitCode); - } - - #endregion - - #region Boostrap the warehouse - - private static MemoryStream DownloadBoostrapFile() - { - Console.WriteLine("Downloading initial Meteor files..."); - DownloadDataCompletedEventArgs download = null; - var complete = new AutoResetEvent(false); - var barWidth = consoleWindowWidth - 5; - using (var client = new WebClient()) - { - if (client.Proxy != null) - { - client.Proxy.Credentials = CredentialCache.DefaultCredentials; - } - client.UseDefaultCredentials = true; - client.DownloadProgressChanged += (sender, e) => - { - var sb = new StringBuilder(); - sb.AppendFormat("\r{0:00} ", e.ProgressPercentage); - int blobs = (barWidth * e.ProgressPercentage) / 100; - for (int i = 0; i < barWidth; i++) sb.Append(i < blobs ? '#' : '-'); - Console.Write(sb.ToString()); - }; - client.DownloadDataCompleted += (sender, e) => - { - download = e; - complete.Set(); - }; - client.DownloadDataAsync(new Uri(BOOTSTRAP_URL)); - } - complete.WaitOne(); - if (download.Error != null) - throw download.Error; - - if (download.Result.Length < 10 * 1024 * 1024 || - (download.Result[0] != 0x1f || download.Result[1] != 0x8b)) - { - throw new InvalidDataException("Unexpected data returned from: " + BOOTSTRAP_URL); - } - - Console.WriteLine(" \rDownload complete ({0:#.#} MB)", download.Result.Length / (1024.0 * 1024.0)); - - var stream = new MemoryStream(download.Result); - download = null; - return stream; - } - - private static void BootstrapWarehouse(string warehouse) - { - MemoryStream stream; - if (bootstrapFile != null) - { - var data = File.ReadAllBytes(bootstrapFile); - stream = new MemoryStream(data); - data = null; - } - else - { - try - { - stream = DownloadBoostrapFile(); - } - catch (Exception) - { - Console.WriteLine("\nERROR: A problem occurred while downloading the bootstrap package."); - Console.WriteLine("\nIf this persists, you can download it manually from:"); - Console.WriteLine(" " + BOOTSTRAP_URL); - Console.WriteLine("and put it in the same directory as LaunchMeteor.exe and run:"); - Console.WriteLine(" LaunchMeteor.exe -downloaded"); - Console.WriteLine("\nHere are some details of the error:"); - throw; - } - } - - Console.WriteLine("Extracting files to {0}", warehouse); - - var tempDir = warehouse + "~"; - if (File.Exists(tempDir)) - File.Delete(tempDir); - DirectoryDelete(tempDir); - - try - { - var regex = new Regex(@"^\.meteor\\"); - ExtractTgz(stream, tempDir, p => regex.Replace(p, "")); - DirectoryDelete(warehouse); - Directory.Move(tempDir, warehouse); - } - catch - { - DirectoryDelete(tempDir); - throw; - } - Console.WriteLine("Files extracted successfully\n"); - - var path = Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.User) ?? string.Empty; - var paths = path.Split(';'); - if (!Array.Exists(paths, p => p.Equals(warehouse, StringComparison.OrdinalIgnoreCase))) - { - Console.WriteLine("Updating PATH to include {0}", warehouse); - path += ((path.Length > 0) ? ";" : "") + warehouse; - Environment.SetEnvironmentVariable("PATH", path, EnvironmentVariableTarget.User); - } - } - - private static void DirectoryDelete(string path) - { - for (int attempt = 1; Directory.Exists(path) && attempt <= 5; attempt++) - { - //if (attempt == 1) - // Console.WriteLine("Deleting directory: {0}", path); - //else - // Console.WriteLine("Deleting directory: {0} attempt {1}", path, attempt); - try { RecursiveDeleteDirectory(path); } catch {} - if (Directory.Exists(path)) - Thread.Sleep(1000); - } - - // Throw the exception - if (Directory.Exists(path)) - RecursiveDeleteDirectory(path); - } - - #endregion - - #region Tar file extraction - - public static void ExtractTgz(string archive, string targetDirectory) - { - using (var fileStream = File.OpenRead(archive)) - { - ExtractTgz(fileStream, targetDirectory, p => p); - } - } - - public static void ExtractTgz(Stream stream, string directory, Func transform) - { - int totalFiles = 0, totalData = 0; - var buffer = new byte[512]; - using (var decompressed = new GZipStream(stream, CompressionMode.Decompress)) - { - string longName = null; - for (int n; (n = decompressed.Read(buffer, 0, buffer.Length)) > 0; ) - { - if (n != buffer.Length) - throw new InvalidDataException("Unexpected end of TAR file"); - - if (TarField(buffer, 257, 5) != "ustar") continue; - - var type = (TarType)buffer[156]; - var length = Convert.ToInt32(TarField(buffer, 124, 12).Trim(), 8); - var link = TarField(buffer, 157, 100); - var path = longName ?? Path.Combine(TarField(buffer, 345, 155), TarField(buffer, 0, 100)); - longName = null; - if (type == TarType.LongName) - { - var data = new MemoryStream(length); - for (; length > 0; length -= buffer.Length) - { - if (decompressed.Read(buffer, 0, buffer.Length) != buffer.Length) - throw new InvalidDataException("Unexpected end of TAR file"); - data.Write(buffer, 0, Math.Min(length, buffer.Length)); - } - longName = TarField(data.ToArray(), 0, (int)data.Length); - continue; - } - - //Console.WriteLine("{0} {1} {2}", type, length.ToString().PadLeft(9), path); - if (type == TarType.AltReg || type == TarType.Reg || type == TarType.Contig || - type == TarType.Sym || type == TarType.Lnk) - { - if (((++totalFiles) & 0xF) == 0) Console.Write("."); - - path = path.Replace('/', '\\'); - if (("\\" + path + "\\").Contains("\\..\\")) - throw new InvalidDataException("Filenames containing '..' are not allowed"); - - path = Path.Combine(directory, transform(path)); - try - { - CreateDirectory(GetDirectoryName(path)); - using (var fstream = CreateWritableFile(path)) - { - if (type == TarType.Lnk || type == TarType.Sym) - { - var data = Encoding.UTF8.GetBytes(link); - fstream.Write(data, 0, data.Length); - length = 0; - } - - totalData += length; - for (; length > 0; length -= buffer.Length) - { - if (decompressed.Read(buffer, 0, buffer.Length) != buffer.Length) - throw new InvalidDataException("Unexpected end of TAR file"); - fstream.Write(buffer, 0, Math.Min(length, buffer.Length)); - } - } - } - catch - { - Console.WriteLine(); - Console.WriteLine("Error processing path: {0}", path); - throw; - } - } - } - Console.WriteLine("\nExtracted {0} files ({1:#.#} MB)", totalFiles, totalData / (1024.0 * 1024.0)); - } - } - - private enum TarType : int { AltReg = 0, Reg = '0', Lnk = '1', Sym = '2', Chr = '3', Blk = '4', Dir = '5', Fifo = '6', Contig = '7', LongName = 'L' } - - private static string TarField(byte[] buffer, int start, int len) - { - var str = Encoding.UTF8.GetString(buffer, start, len); - int pos = str.IndexOf('\0'); - return pos < 0 ? str : str.Substring(0, pos); - } - - #endregion - - // Get directory name (supporting long file names) - private static string GetDirectoryName(string path) - { - path = path.Replace('/', '\\'); - int pos = path.LastIndexOf('\\'); - return (pos >= 0) ? path.Substring(0, pos) : null; - } - - // Create a file, supporting long file names - private static FileStream CreateWritableFile(string path) - { - SafeFileHandle handle = NativeMethods.CreateFile(@"\\?\" + path, - EFileAccess.GenericWrite, EFileShare.None, IntPtr.Zero, - ECreationDisposition.CreateAlways, 0, IntPtr.Zero); - - int error = Marshal.GetLastWin32Error(); - if (handle.IsInvalid) - throw new System.ComponentModel.Win32Exception(error); - - // Pass the file handle to FileStream. FileStream will close it. - return new FileStream(handle, FileAccess.Write); - } - - // Create a directory, supporting long file names - private static void CreateDirectory(string path) - { - bool result = NativeMethods.CreateDirectory(@"\\?\" + path, IntPtr.Zero); - int error = Marshal.GetLastWin32Error(); - if (result || error == NativeMethods.ERROR_ALREADY_EXISTS) - return; - - if (error != NativeMethods.ERROR_PATH_NOT_FOUND) - throw new System.ComponentModel.Win32Exception(error); - - // Try to create parent first, before trying again - CreateDirectory(GetDirectoryName(path)); - CreateDirectory(path); - } - - private static void RecursiveDeleteDirectory(string path) - { - path = path.TrimEnd('\\'); - IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1); - WIN32_FIND_DATA findData; - IntPtr handle = NativeMethods.FindFirstFile(@"\\?\" + path + @"\*", out findData); - if (handle != INVALID_HANDLE_VALUE) - { - for (bool more = true; more; more = NativeMethods.FindNextFile(handle, out findData)) - { - string name = findData.cFileName; - if (((int)findData.dwFileAttributes & NativeMethods.FILE_ATTRIBUTE_DIRECTORY) != 0) - { - if (name != "." && name != "..") - RecursiveDeleteDirectory(Path.Combine(path, name)); - } - else - { - var filePath = @"\\?\" + Path.Combine(path, name); - // Make sure we can still delete if the file is read-only - NativeMethods.SetFileAttributes(filePath, ((int)findData.dwFileAttributes) & ~NativeMethods.FILE_ATTRIBUTE_READONLY); - if (!NativeMethods.DeleteFile(filePath)) - { - int error = Marshal.GetLastWin32Error(); - throw new System.ComponentModel.Win32Exception(error); - } - } - } - } - NativeMethods.FindClose(handle); - - if (!NativeMethods.RemoveDirectory(@"\\?\" + path)) - { - int error = Marshal.GetLastWin32Error(); - throw new System.ComponentModel.Win32Exception(error); - } - } - } - - // PInvoke support for long file names - - internal static class NativeMethods - { - public const int FILE_ATTRIBUTE_DIRECTORY = 0x00000010; - public const int FILE_ATTRIBUTE_READONLY = 0x1; - public const int ERROR_PATH_NOT_FOUND = 3; - public const int ERROR_ALREADY_EXISTS = 183; - - [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - internal static extern SafeFileHandle CreateFile( - string lpFileName, - EFileAccess dwDesiredAccess, - EFileShare dwShareMode, - IntPtr lpSecurityAttributes, - ECreationDisposition dwCreationDisposition, - EFileAttributes dwFlagsAndAttributes, - IntPtr hTemplateFile); - - [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool DeleteFile(string lpFileName); - - [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool CreateDirectory(string lpPathName, IntPtr lpSecurityAttributes); - - [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool RemoveDirectory(string lpPathName); - - [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] - internal static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData); - - [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] - internal static extern bool FindNextFile(IntPtr hFindFile, out WIN32_FIND_DATA lpFindFileData); - - [DllImport("kernel32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool FindClose(IntPtr hFindFile); - - [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] - internal static extern int GetFileAttributes(string lpFileName); - - [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] - internal static extern bool SetFileAttributes(string lpFileName, int dwFileAttributes); - } - - [StructLayout(LayoutKind.Sequential)] - internal struct FILETIME - { - internal uint dwLowDateTime; - internal uint dwHighDateTime; - }; - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - internal struct WIN32_FIND_DATA - { - internal EFileAttributes dwFileAttributes; - internal FILETIME ftCreationTime; - internal FILETIME ftLastAccessTime; - internal FILETIME ftLastWriteTime; - internal int nFileSizeHigh; - internal int nFileSizeLow; - internal int dwReserved0; - internal int dwReserved1; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] - internal string cFileName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] - internal string cAlternate; - } - - [Flags] - public enum EFileAccess : uint - { - GenericRead = 0x80000000, - GenericWrite = 0x40000000, - GenericExecute = 0x20000000, - GenericAll = 0x10000000, - } - - [Flags] - public enum EFileShare : uint - { - None = 0x00000000, - Read = 0x00000001, - Write = 0x00000002, - Delete = 0x00000004, - } - - public enum ECreationDisposition : uint - { - New = 1, - CreateAlways = 2, - OpenExisting = 3, - OpenAlways = 4, - TruncateExisting = 5, - } - - [Flags] - public enum EFileAttributes : uint - { - Readonly = 0x00000001, - Hidden = 0x00000002, - System = 0x00000004, - Directory = 0x00000010, - Archive = 0x00000020, - Device = 0x00000040, - Normal = 0x00000080, - Temporary = 0x00000100, - SparseFile = 0x00000200, - ReparsePoint = 0x00000400, - Compressed = 0x00000800, - Offline = 0x00001000, - NotContentIndexed = 0x00002000, - Encrypted = 0x00004000, - Write_Through = 0x80000000, - Overlapped = 0x40000000, - NoBuffering = 0x20000000, - RandomAccess = 0x10000000, - SequentialScan = 0x08000000, - DeleteOnClose = 0x04000000, - BackupSemantics = 0x02000000, - PosixSemantics = 0x01000000, - OpenReparsePoint = 0x00200000, - OpenNoRecall = 0x00100000, - FirstPipeInstance = 0x00080000 - } -} diff --git a/scripts/windows/build-installer.ps1 b/scripts/windows/build-installer.ps1 index 7450d98c55..dd2dd796d1 100644 --- a/scripts/windows/build-installer.ps1 +++ b/scripts/windows/build-installer.ps1 @@ -1,5 +1,6 @@ $ErrorActionPreference = "Stop" $script_path = (split-path -parent $MyInvocation.MyCommand.Definition) + "\" +$conf_path = $script_path + "wix-installer\WiXInstaller\Configuration.wxi" If ($Args.Count -ne 1) { echo "Usage:" @@ -14,8 +15,26 @@ echo ("Bootstrap tarball version " + $Args[0]) # Set the version $version = $Args[0].replace("`n","").replace("`r","") -(Get-Content ($script_path + "InstallMeteor.cs")) | Foreach-Object {$_ -replace '__METEOR_RELEASE__',$version} | Out-File ($script_path + "InstallMeteor_.cs") +# Numeric part of version, like 1.2.3.4 +$semverVersion = $version.Split("@")[-1] +(Get-Content ($conf_path + "_")) | Foreach-Object { + $_ -replace '__METEOR_RELEASE__',$version ` + -replace '__METEOR_RELEASE_SEMVER__',$semverVersion} | Out-File -Encoding ascii ($conf_path) + +# download 7za.exe, build dependency that we don't want to build from scratch +echo "Downloading binary dependencies: 7za" +$7za_url = "https://s3.amazonaws.com/meteor-windows/build-deps/7za.exe" +$client = new-object System.Net.WebClient +$client.DownloadFile($7za_url, $script_path + "wix-installer\WiXInstaller\Resources\7za.exe") + +Push-Location wix-installer +Invoke-Expression ("cmd /c build.bat") +Pop-Location + +move-item ($script_path + "wix-installer\Release\Setup_Meteor.exe") ($script_path + "InstallMeteor.exe") + +echo "Clean up" +rm $conf_path -Invoke-Expression ($env:WINDIR + "\Microsoft.NET\Framework\v3.5\csc.exe /out:" + $script_path + "InstallMeteor.exe " + $script_path + "InstallMeteor_.cs /debug /nologo") echo "Done" diff --git a/scripts/windows/wix-installer/!ReadMe.txt b/scripts/windows/wix-installer/!ReadMe.txt index 990c1d1ce2..de33be168d 100755 --- a/scripts/windows/wix-installer/!ReadMe.txt +++ b/scripts/windows/wix-installer/!ReadMe.txt @@ -1,29 +1,29 @@ - Meteor WiX Installer - ====================== - -In order to build Meteor installer following tools are required: - Visual Stidio 2010 or later - WiX Toolset 3.8 or later - - -So, the installer was made using WiX Toolset and it uses a custom made WiX extension for boostratpper -project (WixBalExtensionExt.dll), for an improved GUI of bootstrapper application. -The WiX extension was developed on a different solution: WiXBalExtension\BalExtensionExt.sln - -The project have following folders structure: - - + Release - The folder where the compiled installer will be placed - | - + WiXBalExtension - Contain the solution of WiX extension of bootstrapper application - | - + WiXCustomAction - C++ custom action project of the lib that contains custom actions - | used in MSI projects - | - + WiXInstaller - Contain the setup projects of Meteor MSI package and boostratpper project - | - - Resources - Resources files used on both, MSI and bootsreapper projects. - - -The WixBalExtensionExt.dll library was build using VisualStudio 2010, so, if you want to use a differnt one -please make sure that you update Platform Toolset and paths of include/libs on C++ projects - + Meteor WiX Installer + ====================== + +In order to build Meteor installer following tools are required: + Visual Stidio 2010 or later + WiX Toolset 3.8 or later + + +So, the installer was made using WiX Toolset and it uses a custom made WiX extension for boostratpper +project (WixBalExtensionExt.dll), for an improved GUI of bootstrapper application. +The WiX extension was developed on a different solution: WiXBalExtension\BalExtensionExt.sln + +The project have following folders structure: + + + Release - The folder where the compiled installer will be placed + | + + WiXBalExtension - Contain the solution of WiX extension of bootstrapper application + | + + WiXCustomAction - C++ custom action project of the lib that contains custom actions + | used in MSI projects + | + + WiXInstaller - Contain the setup projects of Meteor MSI package and boostratpper project + | + - Resources - Resources files used on both, MSI and bootsreapper projects. + + +The WixBalExtensionExt.dll library was build using VisualStudio 2010, so, if you want to use a differnt one +please make sure that you update Platform Toolset and paths of include/libs on C++ projects + diff --git a/scripts/windows/wix-installer/.gitignore b/scripts/windows/wix-installer/.gitignore index 617d89928b..bf0120d310 100644 --- a/scripts/windows/wix-installer/.gitignore +++ b/scripts/windows/wix-installer/.gitignore @@ -61,7 +61,7 @@ _ReSharper* *.ncrunch* .*crunch*.local.xml -# Installshield output folder +# Installshield output folder [Ee]xpress # DocProject is a documentation generator add-in @@ -108,3 +108,4 @@ Generated_Code #added for RIA/Silverlight projects _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML + diff --git a/scripts/windows/wix-installer/MeteorSetup.sln b/scripts/windows/wix-installer/MeteorSetup.sln index 66866c9db0..343679350b 100755 --- a/scripts/windows/wix-installer/MeteorSetup.sln +++ b/scripts/windows/wix-installer/MeteorSetup.sln @@ -1,29 +1,29 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "MSIPackage", "WiXInstaller\MSIPackage.wixproj", "{E053726B-937B-40C7-8F3D-25A3226979D9}" -EndProject -Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "SetupPackage", "WiXInstaller\SetupPackage.wixproj", "{7B569F5B-5D73-4E7B-BE41-041A2F22A521}" - ProjectSection(ProjectDependencies) = postProject - {E053726B-937B-40C7-8F3D-25A3226979D9} = {E053726B-937B-40C7-8F3D-25A3226979D9} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {E053726B-937B-40C7-8F3D-25A3226979D9}.Release|x64.ActiveCfg = Release|x64 - {E053726B-937B-40C7-8F3D-25A3226979D9}.Release|x64.Build.0 = Release|x64 - {E053726B-937B-40C7-8F3D-25A3226979D9}.Release|x86.ActiveCfg = Release|x86 - {E053726B-937B-40C7-8F3D-25A3226979D9}.Release|x86.Build.0 = Release|x86 - {7B569F5B-5D73-4E7B-BE41-041A2F22A521}.Release|x64.ActiveCfg = Release|x64 - {7B569F5B-5D73-4E7B-BE41-041A2F22A521}.Release|x64.Build.0 = Release|x64 - {7B569F5B-5D73-4E7B-BE41-041A2F22A521}.Release|x86.ActiveCfg = Release|x86 - {7B569F5B-5D73-4E7B-BE41-041A2F22A521}.Release|x86.Build.0 = Release|x86 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "MSIPackage", "WiXInstaller\MSIPackage.wixproj", "{E053726B-937B-40C7-8F3D-25A3226979D9}" +EndProject +Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "SetupPackage", "WiXInstaller\SetupPackage.wixproj", "{7B569F5B-5D73-4E7B-BE41-041A2F22A521}" + ProjectSection(ProjectDependencies) = postProject + {E053726B-937B-40C7-8F3D-25A3226979D9} = {E053726B-937B-40C7-8F3D-25A3226979D9} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E053726B-937B-40C7-8F3D-25A3226979D9}.Release|x64.ActiveCfg = Release|x64 + {E053726B-937B-40C7-8F3D-25A3226979D9}.Release|x64.Build.0 = Release|x64 + {E053726B-937B-40C7-8F3D-25A3226979D9}.Release|x86.ActiveCfg = Release|x86 + {E053726B-937B-40C7-8F3D-25A3226979D9}.Release|x86.Build.0 = Release|x86 + {7B569F5B-5D73-4E7B-BE41-041A2F22A521}.Release|x64.ActiveCfg = Release|x64 + {7B569F5B-5D73-4E7B-BE41-041A2F22A521}.Release|x64.Build.0 = Release|x64 + {7B569F5B-5D73-4E7B-BE41-041A2F22A521}.Release|x86.ActiveCfg = Release|x86 + {7B569F5B-5D73-4E7B-BE41-041A2F22A521}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/scripts/windows/wix-installer/WiXBalExtension/.gitignore b/scripts/windows/wix-installer/WiXBalExtension/.gitignore new file mode 100644 index 0000000000..57a1574c4f --- /dev/null +++ b/scripts/windows/wix-installer/WiXBalExtension/.gitignore @@ -0,0 +1,196 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Visual Studo 2015 cache/options directory +.vs/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding addin-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +*.[Cc]ache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt diff --git a/scripts/windows/wix-installer/WiXBalExtension/BalExtensionExt.sln b/scripts/windows/wix-installer/WiXBalExtension/BalExtensionExt.sln index 4b7bf1d9bb..e7fa75fe30 100755 --- a/scripts/windows/wix-installer/WiXBalExtension/BalExtensionExt.sln +++ b/scripts/windows/wix-installer/WiXBalExtension/BalExtensionExt.sln @@ -1,66 +1,66 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wixextba", "wixstdba\wixstdba.vcxproj", "{41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}" -EndProject -Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "BalExtension", "wixlib\BalExtension.wixproj", "{3444D952-F21C-496F-AB6B-56435BFD0787}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WixBalExtensionExt", "wixext\WixBalExtensionExt.csproj", "{6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}" - ProjectSection(ProjectDependencies) = postProject - {3444D952-F21C-496F-AB6B-56435BFD0787} = {3444D952-F21C-496F-AB6B-56435BFD0787} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|Mixed Platforms = Debug|Mixed Platforms - Debug|Win32 = Debug|Win32 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|Mixed Platforms = Release|Mixed Platforms - Release|Win32 = Release|Win32 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|Any CPU.Build.0 = Debug|Win32 - {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|Win32.ActiveCfg = Debug|Win32 - {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|Win32.Build.0 = Debug|Win32 - {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|x86.ActiveCfg = Debug|Win32 - {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Release|Any CPU.ActiveCfg = Debug|Win32 - {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Release|Mixed Platforms.Build.0 = Release|Win32 - {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Release|Win32.ActiveCfg = Debug|Win32 - {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Release|Win32.Build.0 = Debug|Win32 - {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Release|x86.ActiveCfg = Debug|Win32 - {3444D952-F21C-496F-AB6B-56435BFD0787}.Debug|Any CPU.ActiveCfg = Debug|x86 - {3444D952-F21C-496F-AB6B-56435BFD0787}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {3444D952-F21C-496F-AB6B-56435BFD0787}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {3444D952-F21C-496F-AB6B-56435BFD0787}.Debug|Win32.ActiveCfg = Debug|x86 - {3444D952-F21C-496F-AB6B-56435BFD0787}.Debug|x86.ActiveCfg = Debug|x86 - {3444D952-F21C-496F-AB6B-56435BFD0787}.Debug|x86.Build.0 = Debug|x86 - {3444D952-F21C-496F-AB6B-56435BFD0787}.Release|Any CPU.ActiveCfg = Release|x86 - {3444D952-F21C-496F-AB6B-56435BFD0787}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {3444D952-F21C-496F-AB6B-56435BFD0787}.Release|Mixed Platforms.Build.0 = Release|x86 - {3444D952-F21C-496F-AB6B-56435BFD0787}.Release|Win32.ActiveCfg = Release|x86 - {3444D952-F21C-496F-AB6B-56435BFD0787}.Release|x86.ActiveCfg = Release|x86 - {3444D952-F21C-496F-AB6B-56435BFD0787}.Release|x86.Build.0 = Release|x86 - {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Debug|Win32.ActiveCfg = Debug|Any CPU - {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Debug|x86.ActiveCfg = Debug|Any CPU - {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Release|Any CPU.Build.0 = Release|Any CPU - {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Release|Win32.ActiveCfg = Release|Any CPU - {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Release|x86.ActiveCfg = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wixextba", "wixstdba\wixstdba.vcxproj", "{41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}" +EndProject +Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "BalExtension", "wixlib\BalExtension.wixproj", "{3444D952-F21C-496F-AB6B-56435BFD0787}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WixBalExtensionExt", "wixext\WixBalExtensionExt.csproj", "{6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}" + ProjectSection(ProjectDependencies) = postProject + {3444D952-F21C-496F-AB6B-56435BFD0787} = {3444D952-F21C-496F-AB6B-56435BFD0787} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|Win32 = Debug|Win32 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + Release|Win32 = Release|Win32 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|Any CPU.Build.0 = Debug|Win32 + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|Win32.ActiveCfg = Debug|Win32 + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|Win32.Build.0 = Debug|Win32 + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|x86.ActiveCfg = Debug|Win32 + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Release|Any CPU.ActiveCfg = Debug|Win32 + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Release|Mixed Platforms.Build.0 = Release|Win32 + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Release|Win32.ActiveCfg = Debug|Win32 + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Release|Win32.Build.0 = Debug|Win32 + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Release|x86.ActiveCfg = Debug|Win32 + {3444D952-F21C-496F-AB6B-56435BFD0787}.Debug|Any CPU.ActiveCfg = Debug|x86 + {3444D952-F21C-496F-AB6B-56435BFD0787}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {3444D952-F21C-496F-AB6B-56435BFD0787}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {3444D952-F21C-496F-AB6B-56435BFD0787}.Debug|Win32.ActiveCfg = Debug|x86 + {3444D952-F21C-496F-AB6B-56435BFD0787}.Debug|x86.ActiveCfg = Debug|x86 + {3444D952-F21C-496F-AB6B-56435BFD0787}.Debug|x86.Build.0 = Debug|x86 + {3444D952-F21C-496F-AB6B-56435BFD0787}.Release|Any CPU.ActiveCfg = Release|x86 + {3444D952-F21C-496F-AB6B-56435BFD0787}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {3444D952-F21C-496F-AB6B-56435BFD0787}.Release|Mixed Platforms.Build.0 = Release|x86 + {3444D952-F21C-496F-AB6B-56435BFD0787}.Release|Win32.ActiveCfg = Release|x86 + {3444D952-F21C-496F-AB6B-56435BFD0787}.Release|x86.ActiveCfg = Release|x86 + {3444D952-F21C-496F-AB6B-56435BFD0787}.Release|x86.Build.0 = Release|x86 + {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Debug|Win32.ActiveCfg = Debug|Any CPU + {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Debug|x86.ActiveCfg = Debug|Any CPU + {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Release|Any CPU.Build.0 = Release|Any CPU + {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Release|Win32.ActiveCfg = Release|Any CPU + {6F9B6AFD-538B-4DF6-A1E8-6C224CBD7B05}.Release|x86.ActiveCfg = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/scripts/windows/wix-installer/WiXBalExtension/build.bat b/scripts/windows/wix-installer/WiXBalExtension/build.bat index 67b73aba89..d212696f1e 100755 --- a/scripts/windows/wix-installer/WiXBalExtension/build.bat +++ b/scripts/windows/wix-installer/WiXBalExtension/build.bat @@ -13,7 +13,7 @@ Call :DeleteDir "ipch" %MSBUILD% BalExtensionExt.sln /nologo /verbosity:quiet /t:Rebuild /p:Configuration=Release /p:Platform="Mixed Platforms" /p:RunCodeAnalysis=false /p:DefineConstants="TRACE" /p:OutDir="%outdir%\\" /l:FileLogger,Microsoft.Build.Engine;logfile=build.log if %errorlevel% neq 0 ( echo Build failed - pause + rem pause goto :EOF ) diff --git a/scripts/windows/wix-installer/WiXBalExtension/inc/wixver.cs b/scripts/windows/wix-installer/WiXBalExtension/inc/wixver.cs index 0840422c98..0dfdfece45 100755 --- a/scripts/windows/wix-installer/WiXBalExtension/inc/wixver.cs +++ b/scripts/windows/wix-installer/WiXBalExtension/inc/wixver.cs @@ -1,4 +1,4 @@ // using System.Reflection; [assembly:AssemblyVersion("3.0.0.0")] -[assembly:AssemblyFileVersion("3.7.5533.1995")] +[assembly:AssemblyFileVersion("3.7.5534.8992")] diff --git a/scripts/windows/wix-installer/WiXBalExtension/inc/wixver.h b/scripts/windows/wix-installer/WiXBalExtension/inc/wixver.h index 2dd8ff10d3..6fa064d1ad 100755 --- a/scripts/windows/wix-installer/WiXBalExtension/inc/wixver.h +++ b/scripts/windows/wix-installer/WiXBalExtension/inc/wixver.h @@ -3,11 +3,11 @@ #define _VERSION_FILE_H_ #define szVerMajorMinor "3.7" -#define szVerMajorMinorBuildRev "3.7.5533.1995" +#define szVerMajorMinorBuildRev "3.7.5534.8992" #define rmj 3 #define rmm 7 -#define rbd 5533 -#define rev 1995 +#define rbd 5534 +#define rev 8992 #define szVerName "BalExtensionExt Release" #endif diff --git a/scripts/windows/wix-installer/WiXBalExtension/wixstdba/WixStandardBootstrapperApplication.cpp b/scripts/windows/wix-installer/WiXBalExtension/wixstdba/WixStandardBootstrapperApplication.cpp index 8a5b48345d..a6b94652d3 100755 --- a/scripts/windows/wix-installer/WiXBalExtension/wixstdba/WixStandardBootstrapperApplication.cpp +++ b/scripts/windows/wix-installer/WiXBalExtension/wixstdba/WixStandardBootstrapperApplication.cpp @@ -1,3953 +1,3953 @@ -//------------------------------------------------------------------------------------------------- -// -// Copyright (c) 2004, Outercurve Foundation. -// This software is released under Microsoft Reciprocal License (MS-RL). -// The license and further copyright text can be found in the file -// LICENSE.TXT at the root directory of the distribution. -// -//------------------------------------------------------------------------------------------------- - - -#include "precomp.h" -#include "regutil.h" -#include "JSON.h" - - -static const HRESULT E_WIXSTDBA_CONDITION_FAILED = MAKE_HRESULT(SEVERITY_ERROR, 500, 1); - -static const LPCWSTR WIXBUNDLE_VARIABLE_ELEVATED = L"WixBundleElevated"; - -static const LPCWSTR WIXSTDBA_WINDOW_CLASS = L"WixExtBA"; -static const LPCWSTR WIXSTDBA_VARIABLE_INSTALL_FOLDER = L"InstallFolder"; -static const LPCWSTR WIXSTDBA_VARIABLE_INSTALL_REGPATH = L"InstallRegPath"; -static const LPCWSTR WIXSTDBA_VARIABLE_LAUNCH_TARGET_PATH = L"LaunchTarget"; -static const LPCWSTR WIXSTDBA_VARIABLE_LAUNCH_ARGUMENTS = L"LaunchArguments"; -static const LPCWSTR WIXSTDBA_VARIABLE_LAUNCH_HIDDEN = L"LaunchHidden"; -static const LPCWSTR WIXSTDBA_VARIABLE_LAUNCHAFTERINSTALL_TARGET_PATH = L"LaunchAfterInstallTarget"; -static const LPCWSTR WIXSTDBA_VARIABLE_LAUNCHAFTERINSTALL_ARGUMENTS = L"LaunchAfterInstallArguments"; - -static const LPCWSTR WIXSTDBA_VARIABLE_PROGRESS_HEADER = L"varProgressHeader"; -static const LPCWSTR WIXSTDBA_VARIABLE_PROGRESS_INFO = L"varProgressInfo"; -static const LPCWSTR WIXSTDBA_VARIABLE_SUCCESS_HEADER = L"varSuccessHeader"; -static const LPCWSTR WIXSTDBA_VARIABLE_SUCCESS_INFO = L"varSuccessInfo"; -static const LPCWSTR WIXSTDBA_VARIABLE_FAILURE_HEADER = L"varFailureHeader"; -static const LPCWSTR WIXSTDBA_VARIABLE_SUCCESS_ERRINF = L"varSuccessErrorInfoText"; -static const LPCWSTR WIXSTDBA_VARIABLE_SUCCESS_ERRMSG = L"varSuccessErrorMessageText"; - -static const LPCWSTR WIXSTDBA_VARIABLE_PERMACHINE_INSTALL = L"PerMachineInstall"; -static const LPCWSTR WIXSTDBA_VARIABLE_PERMACHINE_INSTALL_FOLDER = L"PerMachineInstallFolder"; -static const LPCWSTR WIXSTDBA_VARIABLE_PERUSER_INSTALL_FOLDER = L"PerUserInstallFolder"; -static const LPCWSTR WIXSTDBA_VARIABLE_USERMETEORSESSIONFILE = L"UserMeteorSessionFile"; - - -static const LPCWSTR WIXSTDBA_VARIABLE_REG_MAIL = L"RegisterEmail"; -static const LPCWSTR WIXSTDBA_VARIABLE_REG_USER = L"RegisterUser"; -static const LPCWSTR WIXSTDBA_VARIABLE_REG_PASS = L"RegisterPass"; - - - -static const LPCWSTR WIXSTDBA_VARIABLE_LOGSPATH = L"QCInstallLogsPath"; - -static const DWORD WIXSTDBA_ACQUIRE_PERCENTAGE = 1; - -enum WIXSTDBA_STATE -{ - WIXSTDBA_STATE_INSTALLDIR, - WIXSTDBA_STATE_SVC_OPTIONS, - WIXSTDBA_STATE_INITIALIZING, - WIXSTDBA_STATE_INITIALIZED, - WIXSTDBA_STATE_HELP, - WIXSTDBA_STATE_DETECTING, - WIXSTDBA_STATE_DETECTED, - WIXSTDBA_STATE_PLANNING, - WIXSTDBA_STATE_PLANNED, - WIXSTDBA_STATE_APPLYING, - WIXSTDBA_STATE_CACHING, - WIXSTDBA_STATE_CACHED, - WIXSTDBA_STATE_EXECUTING, - WIXSTDBA_STATE_EXECUTED, - WIXSTDBA_STATE_APPLIED, - WIXSTDBA_STATE_FAILED, -}; - -enum WM_WIXSTDBA -{ - WM_WIXSTDBA_SHOW_HELP = WM_APP + 100, - WM_WIXSTDBA_DETECT_PACKAGES, - WM_WIXSTDBA_PLAN_PACKAGES, - WM_WIXSTDBA_APPLY_PACKAGES, - WM_WIXSTDBA_CHANGE_STATE, -}; - -// This enum must be kept in the same order as the vrgwzPageNames array. -enum WIXSTDBA_PAGE -{ - WIXSTDBA_PAGE_LOADING, - WIXSTDBA_PAGE_HELP, - WIXSTDBA_PAGE_INSTALL, - WIXSTDBA_PAGE_INSTALLDIR, - WIXSTDBA_PAGE_SVC_OPTIONS, - WIXSTDBA_PAGE_MODIFY, - WIXSTDBA_PAGE_PROGRESS, - WIXSTDBA_PAGE_PROGRESS_PASSIVE, - WIXSTDBA_PAGE_SUCCESS, - WIXSTDBA_PAGE_FAILURE, - COUNT_WIXSTDBA_PAGE, -}; - -// This array must be kept in the same order as the WIXSTDBA_PAGE enum. -static LPCWSTR vrgwzPageNames[] = { - L"Loading", - L"Help", - L"Install", - L"InstallDir", - L"SvcOptions", - L"Modify", - L"Progress", - L"ProgressPassive", - L"Success", - L"Failure", -}; - -enum WIXSTDBA_CONTROL -{ - // Non-paged controls - WIXSTDBA_CONTROL_CLOSE_BUTTON = THEME_FIRST_ASSIGN_CONTROL_ID, - WIXSTDBA_CONTROL_MINIMIZE_BUTTON, - - // Help page - WIXSTDBA_CONTROL_HELP_CANCEL_BUTTON, - - // Welcome page - WIXSTDBA_CONTROL_INSTALL_BUTTON, - WIXSTDBA_CONTROL_OPTIONS_BUTTON, - WIXSTDBA_CONTROL_EULA_RICHEDIT, - WIXSTDBA_CONTROL_EULA_LINK, - WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX, - WIXSTDBA_CONTROL_WELCOME_CANCEL_BUTTON, - WIXSTDBA_CONTROL_VERSION_LABEL, - WIXSTDBA_CONTROL_UPGRADE_LINK, - WIXSTDBA_CONTROL_NEXT_BUTTON, - WIXSTDBA_CONTROL_BACK_BUTTON, - - - // Options page - WIXSTDBA_CONTROL_PERMACHINE_RADIO, - WIXSTDBA_CONTROL_PERUSER_RADIO, - WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX, - WIXSTDBA_CONTROL_BROWSE_BUTTON, - - WIXSTDBA_CONTROL_REGSIGNIN_RADIO, - WIXSTDBA_CONTROL_REGCREATE_RADIO, - WIXSTDBA_CONTROL_REGMAIL_LABEL, - WIXSTDBA_CONTROL_REGUSER_LABEL, - WIXSTDBA_CONTROL_REGPASS_LABEL, - WIXSTDBA_CONTROL_REGMAIL_EDIT, - WIXSTDBA_CONTROL_REGUSER_EDIT, - WIXSTDBA_CONTROL_REGPASS_EDIT, - WIXSTDBA_CONTROL_SKIPREG_CHECKBOX, - - - WIXSTDBA_CONTROL_OK_BUTTON, - WIXSTDBA_CONTROL_CANCEL_BUTTON, - - // Modify page - WIXSTDBA_CONTROL_REPAIR_BUTTON, - WIXSTDBA_CONTROL_UNINSTALL_BUTTON, - WIXSTDBA_CONTROL_MODIFY_CANCEL_BUTTON, - - // Progress page - WIXSTDBA_CONTROL_CACHE_PROGRESS_PACKAGE_TEXT, - WIXSTDBA_CONTROL_CACHE_PROGRESS_BAR, - WIXSTDBA_CONTROL_CACHE_PROGRESS_TEXT, - - WIXSTDBA_CONTROL_EXECUTE_PROGRESS_PACKAGE_TEXT, - WIXSTDBA_CONTROL_EXECUTE_PROGRESS_BAR, - WIXSTDBA_CONTROL_EXECUTE_PROGRESS_TEXT, - WIXSTDBA_CONTROL_EXECUTE_PROGRESS_ACTIONDATA_TEXT, - - WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, - WIXSTDBA_CONTROL_OVERALL_PROGRESS_BAR, - WIXSTDBA_CONTROL_OVERALL_CALCULATED_PROGRESS_BAR, - WIXSTDBA_CONTROL_OVERALL_PROGRESS_TEXT, - - WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, - - // Success page - WIXSTDBA_CONTROL_LAUNCH_BUTTON, - WIXSTDBA_CONTROL_SUCCESS_RESTART_TEXT, - WIXSTDBA_CONTROL_SUCCESS_RESTART_BUTTON, - WIXSTDBA_CONTROL_SUCCESS_CANCEL_BUTTON, - WIXSTDBA_CONTROL_SUCCESS_ERRINF_TEXT, - WIXSTDBA_CONTROL_SUCCESS_ERRMSG_TEXT, - - // Failure page - WIXSTDBA_CONTROL_FAILURE_LOGFILE_LINK, - WIXSTDBA_CONTROL_FAILURE_MESSAGE_TEXT, - WIXSTDBA_CONTROL_FAILURE_RESTART_TEXT, - WIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON, - WIXSTDBA_CONTROL_FAILURE_CANCEL_BUTTON, -}; - -static THEME_ASSIGN_CONTROL_ID vrgInitControls[] = { - { WIXSTDBA_CONTROL_CLOSE_BUTTON, L"CloseButton" }, - { WIXSTDBA_CONTROL_MINIMIZE_BUTTON, L"MinimizeButton" }, - - { WIXSTDBA_CONTROL_HELP_CANCEL_BUTTON, L"HelpCancelButton" }, - - { WIXSTDBA_CONTROL_INSTALL_BUTTON, L"InstallButton" }, - { WIXSTDBA_CONTROL_OPTIONS_BUTTON, L"OptionsButton" }, - { WIXSTDBA_CONTROL_EULA_RICHEDIT, L"EulaRichedit" }, - { WIXSTDBA_CONTROL_EULA_LINK, L"EulaHyperlink" }, - { WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX, L"EulaAcceptCheckbox" }, - { WIXSTDBA_CONTROL_WELCOME_CANCEL_BUTTON, L"WelcomeCancelButton" }, - { WIXSTDBA_CONTROL_VERSION_LABEL, L"InstallVersion" }, - { WIXSTDBA_CONTROL_UPGRADE_LINK, L"UpgradeHyperlink" }, - { WIXSTDBA_CONTROL_NEXT_BUTTON, L"NextButton" }, - { WIXSTDBA_CONTROL_BACK_BUTTON, L"BackButton" }, - - {WIXSTDBA_CONTROL_PERMACHINE_RADIO, L"PerMachineInstall" }, - {WIXSTDBA_CONTROL_PERUSER_RADIO, L"PerUserInstall" }, - { WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX, L"InstallFolderEditbox" }, - { WIXSTDBA_CONTROL_BROWSE_BUTTON, L"BrowseButton" }, - - {WIXSTDBA_CONTROL_REGSIGNIN_RADIO, L"SignInRButton"}, - {WIXSTDBA_CONTROL_REGCREATE_RADIO, L"CreateRButton"}, - {WIXSTDBA_CONTROL_REGMAIL_LABEL, L"RegisterEmailLabel"}, - {WIXSTDBA_CONTROL_REGUSER_LABEL, L"RegisterUserLabel"}, - {WIXSTDBA_CONTROL_REGPASS_LABEL, L"RegisterPassLabel"}, - {WIXSTDBA_CONTROL_REGMAIL_EDIT, L"RegisterEmail"}, - {WIXSTDBA_CONTROL_REGUSER_EDIT, L"RegisterUser"}, - {WIXSTDBA_CONTROL_REGPASS_EDIT, L"RegisterPass"}, - {WIXSTDBA_CONTROL_SKIPREG_CHECKBOX, L"SkipRegistration"}, - - { WIXSTDBA_CONTROL_REPAIR_BUTTON, L"RepairButton" }, - { WIXSTDBA_CONTROL_UNINSTALL_BUTTON, L"UninstallButton" }, - { WIXSTDBA_CONTROL_MODIFY_CANCEL_BUTTON, L"ModifyCancelButton" }, - - { WIXSTDBA_CONTROL_CACHE_PROGRESS_PACKAGE_TEXT, L"CacheProgressPackageText" }, - { WIXSTDBA_CONTROL_CACHE_PROGRESS_BAR, L"CacheProgressbar" }, - { WIXSTDBA_CONTROL_CACHE_PROGRESS_TEXT, L"CacheProgressText" }, - { WIXSTDBA_CONTROL_EXECUTE_PROGRESS_PACKAGE_TEXT, L"ExecuteProgressPackageText" }, - { WIXSTDBA_CONTROL_EXECUTE_PROGRESS_BAR, L"ExecuteProgressbar" }, - { WIXSTDBA_CONTROL_EXECUTE_PROGRESS_TEXT, L"ExecuteProgressText" }, - { WIXSTDBA_CONTROL_EXECUTE_PROGRESS_ACTIONDATA_TEXT, L"ExecuteProgressActionDataText"}, - { WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, L"OverallProgressPackageText" }, - { WIXSTDBA_CONTROL_OVERALL_PROGRESS_BAR, L"OverallProgressbar" }, - { WIXSTDBA_CONTROL_OVERALL_CALCULATED_PROGRESS_BAR, L"OverallCalculatedProgressbar" }, - { WIXSTDBA_CONTROL_OVERALL_PROGRESS_TEXT, L"OverallProgressText" }, - { WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, L"ProgressCancelButton" }, - - { WIXSTDBA_CONTROL_LAUNCH_BUTTON, L"LaunchButton" }, - { WIXSTDBA_CONTROL_SUCCESS_RESTART_TEXT, L"SuccessRestartText" }, - { WIXSTDBA_CONTROL_SUCCESS_RESTART_BUTTON, L"SuccessRestartButton" }, - { WIXSTDBA_CONTROL_SUCCESS_CANCEL_BUTTON, L"SuccessCancelButton" }, - { WIXSTDBA_CONTROL_SUCCESS_ERRINF_TEXT, L"SuccessErrorInfoText" }, - { WIXSTDBA_CONTROL_SUCCESS_ERRMSG_TEXT, L"SuccessErrorMessageText" }, - - { WIXSTDBA_CONTROL_FAILURE_LOGFILE_LINK, L"FailureLogFileLink" }, - { WIXSTDBA_CONTROL_FAILURE_MESSAGE_TEXT, L"FailureMessageText" }, - { WIXSTDBA_CONTROL_FAILURE_RESTART_TEXT, L"FailureRestartText" }, - { WIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON, L"FailureRestartButton" }, - { WIXSTDBA_CONTROL_FAILURE_CANCEL_BUTTON, L"FailureCloseButton" }, -}; - - -void ExtractActionProgressText( - __in_z LPCWSTR wzActionMessage, - __in_z LPCWSTR *pwzActionProgressText - ) -{ - if (!wzActionMessage) - return; - - DWORD i = 0; - LPCWSTR wzActionProgressText = wzActionMessage; - - LPCWSTR wz = wzActionMessage; - while (*wz) - { - if (L' ' == *wz) ++i; - if (i <= 2) wzActionProgressText++; - - ++wz; - } - *pwzActionProgressText = wzActionProgressText; - - return; -} - - - - -class CWixStandardBootstrapperApplication : public CBalBaseBootstrapperApplication -{ -public: // IBootstrapperApplication - virtual STDMETHODIMP OnStartup() - { - HRESULT hr = S_OK; - DWORD dwUIThreadId = 0; - - // create UI thread - m_hUiThread = ::CreateThread(NULL, 0, UiThreadProc, this, 0, &dwUIThreadId); - if (!m_hUiThread) - { - ExitWithLastError(hr, "Failed to create UI thread."); - } - -LExit: - return hr; - } - - - virtual STDMETHODIMP_(int) OnShutdown() - { - int nResult = IDNOACTION; - - // wait for UI thread to terminate - if (m_hUiThread) - { - ::WaitForSingleObject(m_hUiThread, INFINITE); - ReleaseHandle(m_hUiThread); - } - - // If a restart was required. - if (m_fRestartRequired) - { - if (m_fAllowRestart) - { - nResult = IDRESTART; - } - - if (m_sczPrereqPackage) - { - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, m_fAllowRestart ? "The prerequisites scheduled a restart. The bootstrapper application will be reloaded after the computer is restarted." - : "A restart is required by the prerequisites but the user delayed it. The bootstrapper application will be reloaded after the computer is restarted."); - } - } - else if (m_fPrereqInstalled) - { - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "The prerequisites were successfully installed. The bootstrapper application will be reloaded."); - nResult = IDRELOAD_BOOTSTRAPPER; - } - else if (m_fPrereqAlreadyInstalled) - { - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "The prerequisites were already installed. The bootstrapper application will not be reloaded to prevent an infinite loop."); - } - else if (m_fPrereq) - { - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "The prerequisites were not successfully installed, error: 0x%x. The bootstrapper application will be not reloaded.", m_hrFinal); - } - - return nResult; - } - - - virtual STDMETHODIMP_(int) OnDetectRelatedBundle( - __in LPCWSTR wzBundleId, - __in BOOTSTRAPPER_RELATION_TYPE relationType, - __in LPCWSTR /*wzBundleTag*/, - __in BOOL fPerMachine, - __in DWORD64 /*dw64Version*/, - __in BOOTSTRAPPER_RELATED_OPERATION operation - ) - { - BalInfoAddRelatedBundleAsPackage(&m_Bundle.packages, wzBundleId, relationType, fPerMachine); - // If we're not doing a pre-req install, remember when our bundle would cause a downgrade. - if (!m_sczPrereqPackage && BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE == operation) - { - m_fDowngrading = TRUE; - } - - m_Operation = operation; // Save operation - - return CheckCanceled() ? IDCANCEL : IDOK; - } - - - virtual STDMETHODIMP_(void) OnDetectPackageComplete( - __in LPCWSTR wzPackageId, - __in HRESULT /*hrStatus*/, - __in BOOTSTRAPPER_PACKAGE_STATE state - ) - { - // If the prereq package is already installed, remember that. - if (m_sczPrereqPackage && BOOTSTRAPPER_PACKAGE_STATE_PRESENT == state && - CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzPackageId, -1, m_sczPrereqPackage, -1)) - { - m_fPrereqAlreadyInstalled = TRUE; - } - } - - - // OnDetectUpdateBegin - called when the engine begins detection for bundle update. - virtual STDMETHODIMP_(int) OnDetectUpdateBegin( - __in_z LPCWSTR wzUpdateLocation, - __in int nRecommendation - ) - { - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Update location: %ls.", wzUpdateLocation); - - m_wzUpdateLocation = wzUpdateLocation; - // If there is an upgrade link, check for update on a background thread - if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_UPGRADE_LINK)) - { - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_UPGRADE_LINK, FALSE); - ::CreateThread(NULL, 0, ThreadProc, this, 0, NULL); - } - - return nRecommendation; - } - - - virtual STDMETHODIMP_(int) OnDetectBegin( - __in BOOL /*fInstalled*/, - __in DWORD /*cPackages*/ - ) - { - return IDNOACTION; - } - - - virtual STDMETHODIMP_(void) OnDetectComplete( - __in HRESULT hrStatus - ) - { - if (SUCCEEDED(hrStatus) && m_pBAFunction) - { - m_pBAFunction->OnDetectComplete(); - } - - if (SUCCEEDED(hrStatus)) - { - hrStatus = EvaluateConditions(); - } - - SetState(WIXSTDBA_STATE_DETECTED, hrStatus); - - // Doing some custom vars handling - //if (BalStringVariableExists(WIXSTDBA_VARIABLE_DETECT_POSTGRES)) - //{ - // LONGLONG llValue = 0; - // BalGetNumericVariable(WIXSTDBA_VARIABLE_DETECT_POSTGRES, &llValue); - // if (llValue == 1) - // m_pEngine->SetVariableNumeric(WIXSTDBA_VARIABLE_INSTALL_POSTGRES, 0); - //} - - - // If we're not interacting with the user or we're doing a layout or we're just after a force restart - // then automatically start planning. - if (BOOTSTRAPPER_DISPLAY_FULL > m_command.display || BOOTSTRAPPER_ACTION_LAYOUT == m_command.action || BOOTSTRAPPER_RESUME_TYPE_REBOOT == m_command.resumeType) - { - if (SUCCEEDED(hrStatus)) - { - ::PostMessageW(m_hWnd, WM_WIXSTDBA_PLAN_PACKAGES, 0, m_command.action); - } - } - } - - - virtual STDMETHODIMP_(int) OnPlanRelatedBundle( - __in_z LPCWSTR /*wzBundleId*/, - __inout_z BOOTSTRAPPER_REQUEST_STATE* pRequestedState - ) - { - // If we're only installing prereq, do not touch related bundles. - if (m_sczPrereqPackage) - { - *pRequestedState = BOOTSTRAPPER_REQUEST_STATE_NONE; - } - else if (BOOTSTRAPPER_RELATED_OPERATION_NONE == m_Operation && - BOOTSTRAPPER_REQUEST_STATE_NONE == *pRequestedState && - BOOTSTRAPPER_RELATION_UPGRADE != m_command.relationType) - { - // Same version upgrade detected, mark absent so the install runs - *pRequestedState = BOOTSTRAPPER_REQUEST_STATE_ABSENT; - } - - return CheckCanceled() ? IDCANCEL : IDOK; - } - - - virtual STDMETHODIMP_(int) OnPlanPackageBegin( - __in_z LPCWSTR wzPackageId, - __inout BOOTSTRAPPER_REQUEST_STATE *pRequestState - ) - { - // If we're planning to install a pre-req, install it. The pre-req needs to be installed - // in all cases (even uninstall!) so the BA can load next. - if (m_sczPrereqPackage) - { - if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzPackageId, -1, m_sczPrereqPackage, -1)) - { - *pRequestState = BOOTSTRAPPER_REQUEST_STATE_PRESENT; - } - else // skip everything else. - { - *pRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE; - } - } - else if (m_sczAfterForcedRestartPackage) // after force restart skip packages until after the package that caused the restart. - { - // After restart we need to finish the dependency registration for our package so allow the package - // to go present. - if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzPackageId, -1, m_sczAfterForcedRestartPackage, -1)) - { - // Do not allow a repair because that could put us in a perpetual restart loop. - if (BOOTSTRAPPER_REQUEST_STATE_REPAIR == *pRequestState) - { - *pRequestState = BOOTSTRAPPER_REQUEST_STATE_PRESENT; - } - - ReleaseNullStr(m_sczAfterForcedRestartPackage); // no more skipping now. - } - else // not the matching package, so skip it. - { - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Skipping package: %ls, after restart because it was applied before the restart.", wzPackageId); - - *pRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE; - } - } - - return CheckCanceled() ? IDCANCEL : IDOK; - } - - - virtual STDMETHODIMP_(void) OnPlanComplete( - __in HRESULT hrStatus - ) - { - if (SUCCEEDED(hrStatus) && m_pBAFunction) - { - m_pBAFunction->OnPlanComplete(); - } - - SetState(WIXSTDBA_STATE_PLANNED, hrStatus); - - if (SUCCEEDED(hrStatus)) - { - ::PostMessageW(m_hWnd, WM_WIXSTDBA_APPLY_PACKAGES, 0, 0); - } - - m_fStartedExecution = FALSE; - m_dwCalculatedCacheProgress = 0; - m_dwCalculatedExecuteProgress = 0; - } - - - virtual STDMETHODIMP_(int) OnCachePackageBegin( - __in_z LPCWSTR wzPackageId, - __in DWORD cCachePayloads, - __in DWORD64 dw64PackageCacheSize - ) - { - if (wzPackageId && *wzPackageId) - { - BAL_INFO_PACKAGE* pPackage = NULL; - HRESULT hr = BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage); - LPCWSTR wz = (SUCCEEDED(hr) && pPackage->sczDisplayName) ? pPackage->sczDisplayName : wzPackageId; - - WCHAR wzInfo[1024] = { }; - ::StringCchPrintfW(wzInfo, countof(wzInfo), L"Acquiring %s package...", wz); - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_CACHE_PROGRESS_PACKAGE_TEXT, wzInfo); - // If something started executing, leave it in the overall progress text. - if (!m_fStartedExecution) - { - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, wzInfo); - } - } - - return __super::OnCachePackageBegin(wzPackageId, cCachePayloads, dw64PackageCacheSize); - } - - virtual STDMETHODIMP_(int) OnCacheAcquireProgress( - __in_z LPCWSTR wzPackageOrContainerId, - __in_z_opt LPCWSTR wzPayloadId, - __in DWORD64 dw64Progress, - __in DWORD64 dw64Total, - __in DWORD dwOverallPercentage - ) - { - WCHAR wzProgress[5] = { }; - -#ifdef DEBUG - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: OnCacheAcquireProgress() - container/package: %ls, payload: %ls, progress: %I64u, total: %I64u, overall progress: %u%%", wzPackageOrContainerId, wzPayloadId, dw64Progress, dw64Total, dwOverallPercentage); -#endif - - ::StringCchPrintfW(wzProgress, countof(wzProgress), L"%u%%", dwOverallPercentage); - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_CACHE_PROGRESS_TEXT, wzProgress); - ThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_CACHE_PROGRESS_BAR, dwOverallPercentage); - - BAL_INFO_PACKAGE* pPackage = NULL; - HRESULT hr = BalInfoFindPackageById(&m_Bundle.packages, wzPackageOrContainerId, &pPackage); - LPCWSTR wzPackageName = (SUCCEEDED(hr) && pPackage->sczDisplayName) ? pPackage->sczDisplayName : wzPackageOrContainerId; - - WCHAR wzInfo[1024] = { }; - ::StringCchPrintfW(wzInfo, countof(wzInfo), L"Acquiring %s package... [ %u%% ]", wzPackageName, dwOverallPercentage); - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, wzInfo); - - // Restrict progress to 100% to hide burn engine progress bug. - // m_dwCalculatedCacheProgress = min(dwOverallPercentage, 100) * WIXSTDBA_ACQUIRE_PERCENTAGE / 100; - -#ifdef DEBUG - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: OnCacheAcquireProgress() - calculated progress: %u%%, displayed progress: %u%%", m_dwCalculatedCacheProgress, m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress); -#endif - m_dwCalculatedCacheProgress = dwOverallPercentage * WIXSTDBA_ACQUIRE_PERCENTAGE / 100; - ThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_CALCULATED_PROGRESS_BAR, m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress); - - SetTaskbarButtonProgress(m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress); - - return __super::OnCacheAcquireProgress(wzPackageOrContainerId, wzPayloadId, dw64Progress, dw64Total, dwOverallPercentage); - } - - - virtual STDMETHODIMP_(int) OnCacheAcquireComplete( - __in_z LPCWSTR wzPackageOrContainerId, - __in_z_opt LPCWSTR wzPayloadId, - __in HRESULT hrStatus, - __in int nRecommendation - ) - { - SetProgressState(hrStatus); - return __super::OnCacheAcquireComplete(wzPackageOrContainerId, wzPayloadId, hrStatus, nRecommendation); - } - - - virtual STDMETHODIMP_(int) OnCacheVerifyComplete( - __in_z LPCWSTR wzPackageId, - __in_z LPCWSTR wzPayloadId, - __in HRESULT hrStatus, - __in int nRecommendation - ) - { - SetProgressState(hrStatus); - return __super::OnCacheVerifyComplete(wzPackageId, wzPayloadId, hrStatus, nRecommendation); - } - - virtual STDMETHODIMP_(void) OnCacheComplete( - __in HRESULT /*hrStatus*/ - ) - { - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_CACHE_PROGRESS_PACKAGE_TEXT, L""); - SetState(WIXSTDBA_STATE_CACHED, S_OK); // we always return success here and let OnApplyComplete() deal with the error. - } - - - virtual STDMETHODIMP_(int) OnError( - __in BOOTSTRAPPER_ERROR_TYPE errorType, - __in LPCWSTR wzPackageId, - __in DWORD dwCode, - __in_z LPCWSTR wzError, - __in DWORD dwUIHint, - __in DWORD /*cData*/, - __in_ecount_z_opt(cData) LPCWSTR* /*rgwzData*/, - __in int nRecommendation - ) - { - int nResult = nRecommendation; - LPWSTR sczError = NULL; - - if (BOOTSTRAPPER_DISPLAY_EMBEDDED == m_command.display) - { - HRESULT hr = m_pEngine->SendEmbeddedError(dwCode, wzError, dwUIHint, &nResult); - if (FAILED(hr)) - { - nResult = IDERROR; - } - } - else if (BOOTSTRAPPER_DISPLAY_FULL == m_command.display) - { - // If this is an authentication failure, let the engine try to handle it for us. - if (BOOTSTRAPPER_ERROR_TYPE_HTTP_AUTH_SERVER == errorType || BOOTSTRAPPER_ERROR_TYPE_HTTP_AUTH_PROXY == errorType) - { - nResult = IDTRYAGAIN; - } - else // show a generic error message box. - { - BalRetryErrorOccurred(wzPackageId, dwCode); - - if (!m_fShowingInternalUiThisPackage) - { - // If no error message was provided, use the error code to try and get an error message. - if (!wzError || !*wzError || BOOTSTRAPPER_ERROR_TYPE_WINDOWS_INSTALLER != errorType) - { - HRESULT hr = StrAllocFromError(&sczError, dwCode, NULL); - if (FAILED(hr) || !sczError || !*sczError) - { - StrAllocFormatted(&sczError, L"0x%x", dwCode); - } - } - - nResult = ::MessageBoxW(m_hWnd, sczError ? sczError : wzError, m_pTheme->sczCaption, dwUIHint); - } - } - - SetProgressState(HRESULT_FROM_WIN32(dwCode)); - } - else // just take note of the error code and let things continue. - { - BalRetryErrorOccurred(wzPackageId, dwCode); - } - - ReleaseStr(sczError); - return nResult; - } - - - virtual STDMETHODIMP_(int) OnExecuteMsiMessage( - __in_z LPCWSTR wzPackageId, - __in INSTALLMESSAGE mt, - __in UINT uiFlags, - __in_z LPCWSTR wzMessage, - __in DWORD cData, - __in_ecount_z_opt(cData) LPCWSTR* rgwzData, - __in int nRecommendation - ) - { -#ifdef DEBUG - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: OnExecuteMsiMessage() - package: %ls, message: %ls", wzPackageId, wzMessage); -#endif - if (BOOTSTRAPPER_DISPLAY_FULL == m_command.display && (INSTALLMESSAGE_WARNING == mt || INSTALLMESSAGE_USER == mt)) - { - int nResult = ::MessageBoxW(m_hWnd, wzMessage, m_pTheme->sczCaption, uiFlags); - return nResult; - } - - if (INSTALLMESSAGE_ACTIONSTART == mt) - { - LPCWSTR wzActionProgressText = NULL; - ExtractActionProgressText(wzMessage, &wzActionProgressText); - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_ACTIONDATA_TEXT, wzActionProgressText); - } - - return __super::OnExecuteMsiMessage(wzPackageId, mt, uiFlags, wzMessage, cData, rgwzData, nRecommendation); - } - - - virtual STDMETHODIMP_(int) OnProgress( - __in DWORD dwProgressPercentage, - __in DWORD dwOverallProgressPercentage - ) - { - WCHAR wzProgress[5] = { }; - -#ifdef DEBUG - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: OnProgress() - progress: %u%%, overall progress: %u%%", dwProgressPercentage, dwOverallProgressPercentage); -#endif - - ::StringCchPrintfW(wzProgress, countof(wzProgress), L"%u%%", dwOverallProgressPercentage); - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_TEXT, wzProgress); - - ThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_BAR, dwOverallProgressPercentage); - SetTaskbarButtonProgress(dwOverallProgressPercentage); - - return __super::OnProgress(dwProgressPercentage, dwOverallProgressPercentage); - } - - - virtual STDMETHODIMP_(int) OnExecutePackageBegin( - __in_z LPCWSTR wzPackageId, - __in BOOL fExecute - ) - { - LPWSTR sczFormattedString = NULL; - - m_fStartedExecution = TRUE; - - if (wzPackageId && *wzPackageId) - { - BAL_INFO_PACKAGE* pPackage = NULL; - BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage); - - LPCWSTR wz = wzPackageId; - if (pPackage) - { - LOC_STRING* pLocString = NULL; - - switch (pPackage->type) - { - case BAL_INFO_PACKAGE_TYPE_BUNDLE_ADDON: - LocGetString(m_pWixLoc, L"#(loc.ExecuteAddonRelatedBundleMessage)", &pLocString); - break; - - case BAL_INFO_PACKAGE_TYPE_BUNDLE_PATCH: - LocGetString(m_pWixLoc, L"#(loc.ExecutePatchRelatedBundleMessage)", &pLocString); - break; - - case BAL_INFO_PACKAGE_TYPE_BUNDLE_UPGRADE: - LocGetString(m_pWixLoc, L"#(loc.ExecuteUpgradeRelatedBundleMessage)", &pLocString); - break; - } - - if (pLocString) - { - BalFormatString(pLocString->wzText, &sczFormattedString); - } - - wz = sczFormattedString ? sczFormattedString : pPackage->sczDisplayName ? pPackage->sczDisplayName : wzPackageId; - } - - m_fShowingInternalUiThisPackage = pPackage && pPackage->fDisplayInternalUI; - - WCHAR wzInfo[1024] = { }; - if (m_fIsUninstall) - ::StringCchPrintfW(wzInfo, countof(wzInfo), L"Uninstalling %s ...", wz); - else - ::StringCchPrintfW(wzInfo, countof(wzInfo), L"Installing %s ...", wz); - - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_PACKAGE_TEXT, wz); - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, wz); - } - else - { - m_fShowingInternalUiThisPackage = FALSE; - } - - ReleaseStr(sczFormattedString); - return __super::OnExecutePackageBegin(wzPackageId, fExecute); - } - - virtual int __stdcall OnExecuteProgress( - __in_z LPCWSTR wzPackageId, - __in DWORD dwProgressPercentage, - __in DWORD dwOverallProgressPercentage - ) - { - WCHAR wzProgress[5] = { }; - -#ifdef DEBUG - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: OnExecuteProgress() - package: %ls, progress: %u%%, overall progress: %u%%", wzPackageId, dwProgressPercentage, dwOverallProgressPercentage); -#endif - - ::StringCchPrintfW(wzProgress, countof(wzProgress), L"%u%%", dwOverallProgressPercentage); - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_TEXT, wzProgress); - ThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_BAR, dwOverallProgressPercentage); - - BAL_INFO_PACKAGE* pPackage = NULL; - HRESULT hr = BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage); - LPCWSTR wzPackageName = (SUCCEEDED(hr) && pPackage->sczDisplayName) ? pPackage->sczDisplayName : wzPackageId; - - WCHAR wzInfo[1024] = { }; - if (m_fIsUninstall) - ::StringCchPrintfW(wzInfo, countof(wzInfo), L"Uninstalling %s ... [ %u%% ]", wzPackageName, dwProgressPercentage); - else - ::StringCchPrintfW(wzInfo, countof(wzInfo), L"Installing %s ... [ %u%% ]", wzPackageName, dwProgressPercentage); - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, wzInfo); - - m_dwCalculatedExecuteProgress = dwOverallProgressPercentage * (100 - WIXSTDBA_ACQUIRE_PERCENTAGE) / 100; -#ifdef DEBUG - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: OnExecuteProgress() - calculated progress: %u%%, displayed progress: %u%%", m_dwCalculatedExecuteProgress, m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress); -#endif - ThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_CALCULATED_PROGRESS_BAR, m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress); - - SetTaskbarButtonProgress(m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress); - - return __super::OnExecuteProgress(wzPackageId, dwProgressPercentage, dwOverallProgressPercentage); - } - - - virtual STDMETHODIMP_(int) OnExecutePackageComplete( - __in_z LPCWSTR wzPackageId, - __in HRESULT hrExitCode, - __in BOOTSTRAPPER_APPLY_RESTART restart, - __in int nRecommendation - ) - { - SetProgressState(hrExitCode); - - int nResult = __super::OnExecutePackageComplete(wzPackageId, hrExitCode, restart, nRecommendation); - - if (m_sczPrereqPackage && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzPackageId, -1, m_sczPrereqPackage, -1)) - { - m_fPrereqInstalled = SUCCEEDED(hrExitCode); - - // If the pre-req required a restart (any restart) then do an immediate - // restart to ensure that the bundle will get launched again post reboot. - if (BOOTSTRAPPER_APPLY_RESTART_NONE != restart) - { - nResult = IDRESTART; - } - } - - - /// On package install complete, if WIXSTDBA_VARIABLE_LOGSPATH is defined - /// then will move the package installation log to the specified path. - if (BalStringVariableExists(WIXSTDBA_VARIABLE_LOGSPATH)) - { - LPWSTR wzVarPackageLog = NULL; - StrAllocFormatted(&wzVarPackageLog, L"WixBundleLog_%s", wzPackageId); - if (BalStringVariableExists(wzVarPackageLog)) - { - LPWSTR wzPackageLog = NULL; - LPWSTR wzInstallLogPath = NULL; - LPWSTR wzDstPackageLog = NULL; - - if ( SUCCEEDED(BalGetStringVariable(WIXSTDBA_VARIABLE_LOGSPATH, &wzInstallLogPath)) && - SUCCEEDED(BalGetStringVariable(wzVarPackageLog, &wzPackageLog))) - { - StrAllocFormatted(&wzDstPackageLog, L"%s\\%s", wzInstallLogPath, PathFile(wzPackageLog)); - DirEnsureExists(wzInstallLogPath, NULL); - FileEnsureMove(wzPackageLog, wzDstPackageLog, TRUE, TRUE); - } else - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Setup was unable to copy logs to the specified installation log path."); - - } - } - - return nResult; - } - - - virtual STDMETHODIMP_(void) OnExecuteComplete( - __in HRESULT hrStatus - ) - { - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_PACKAGE_TEXT, L""); - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_ACTIONDATA_TEXT, L""); - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, L""); - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, FALSE); // no more cancel. - - SetState(WIXSTDBA_STATE_EXECUTED, S_OK); // we always return success here and let OnApplyComplete() deal with the error. - SetProgressState(hrStatus); - } - - /* - virtual STDMETHODIMP_(int) OnResolveSource( - __in_z LPCWSTR wzPackageOrContainerId, - __in_z_opt LPCWSTR wzPayloadId, - __in_z LPCWSTR wzLocalSource, - __in_z_opt LPCWSTR wzDownloadSource - ) - { - int nResult = IDERROR; // assume we won't resolve source and that is unexpected. - - LPWSTR sczHTTPDwnUserName = NULL; - LPWSTR sczHTTPDwnPassword = NULL; - LPWSTR sczHTTPDwnHost = NULL; - BOOL bUseHTTPAuth = FALSE; - BOOL bUpdateDwnSrc = FALSE; - - - - if (BOOTSTRAPPER_DISPLAY_FULL == m_command.display) - { - if (wzDownloadSource) - { - if (bUseHTTPAuth || bUpdateDwnSrc) - { - HRESULT hr = m_pEngine->SetDownloadSource(wzPackageOrContainerId, wzPayloadId, wzDownloadSource, sczHTTPDwnUserName, sczHTTPDwnPassword); - nResult = SUCCEEDED(hr) ? IDDOWNLOAD : IDERROR; - } - else - nResult = IDDOWNLOAD; - } - else // prompt to change the source location. - { - OPENFILENAMEW ofn = { }; - WCHAR wzFile[MAX_PATH] = { }; - - ::StringCchCopyW(wzFile, countof(wzFile), wzLocalSource); - - ofn.lStructSize = sizeof(ofn); - ofn.hwndOwner = m_hWnd; - ofn.lpstrFile = wzFile; - ofn.nMaxFile = countof(wzFile); - ofn.lpstrFilter = L"All Files\0*.*\0"; - ofn.nFilterIndex = 1; - ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; - ofn.lpstrTitle = m_pTheme->sczCaption; - - if (::GetOpenFileNameW(&ofn)) - { - HRESULT hr = m_pEngine->SetLocalSource(wzPackageOrContainerId, wzPayloadId, ofn.lpstrFile); - nResult = SUCCEEDED(hr) ? IDRETRY : IDERROR; - } - else - { - nResult = IDCANCEL; - } - } - } - else if (wzDownloadSource) - { - // If doing a non-interactive install and download source is available, let's try downloading the package silently - if (bUseHTTPAuth || bUpdateDwnSrc) - { - HRESULT hr = m_pEngine->SetDownloadSource(wzPackageOrContainerId, wzPayloadId, wzDownloadSource, sczHTTPDwnUserName, sczHTTPDwnPassword); - nResult = SUCCEEDED(hr) ? IDRETRY : IDERROR; - } - else - nResult = IDDOWNLOAD; - } - // else there's nothing more we can do in non-interactive mode - - return CheckCanceled() ? IDCANCEL : nResult; - } - */ - - virtual STDMETHODIMP_(int) OnResolveSource( - __in_z LPCWSTR wzPackageOrContainerId, - __in_z_opt LPCWSTR wzPayloadId, - __in_z LPCWSTR wzLocalSource, - __in_z_opt LPCWSTR wzDownloadSource - ) - { - int nResult = IDERROR; // assume we won't resolve source and that is unexpected. - - if (BOOTSTRAPPER_DISPLAY_FULL == m_command.display) - { - if (wzDownloadSource) - { - nResult = IDDOWNLOAD; - } - else // prompt to change the source location. - { - OPENFILENAMEW ofn = { }; - WCHAR wzFile[MAX_PATH] = { }; - - ::StringCchCopyW(wzFile, countof(wzFile), wzLocalSource); - - ofn.lStructSize = sizeof(ofn); - ofn.hwndOwner = m_hWnd; - ofn.lpstrFile = wzFile; - ofn.nMaxFile = countof(wzFile); - ofn.lpstrFilter = L"All Files\0*.*\0"; - ofn.nFilterIndex = 1; - ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; - ofn.lpstrTitle = m_pTheme->sczCaption; - - if (::GetOpenFileNameW(&ofn)) - { - HRESULT hr = m_pEngine->SetLocalSource(wzPackageOrContainerId, wzPayloadId, ofn.lpstrFile); - nResult = SUCCEEDED(hr) ? IDRETRY : IDERROR; - } - else - { - nResult = IDCANCEL; - } - } - } - else if (wzDownloadSource) - { - // If doing a non-interactive install and download source is available, let's try downloading the package silently - nResult = IDDOWNLOAD; - } - // else there's nothing more we can do in non-interactive mode - - return CheckCanceled() ? IDCANCEL : nResult; - } - - - virtual STDMETHODIMP_(int) OnApplyComplete( - __in HRESULT hrStatus, - __in BOOTSTRAPPER_APPLY_RESTART restart - ) - { - m_restartResult = restart; // remember the restart result so we return the correct error code no matter what the user chooses to do in the UI. - - // If a restart was encountered and we are not suppressing restarts, then restart is required. - m_fRestartRequired = (BOOTSTRAPPER_APPLY_RESTART_NONE != restart && BOOTSTRAPPER_RESTART_NEVER < m_command.restart); - // If a restart is required and we're not displaying a UI or we are not supposed to prompt for restart then allow the restart. - m_fAllowRestart = m_fRestartRequired && (BOOTSTRAPPER_DISPLAY_FULL > m_command.display || BOOTSTRAPPER_RESTART_PROMPT < m_command.restart); - - // If we are showing UI, wait a beat before moving to the final screen. - if (BOOTSTRAPPER_DISPLAY_NONE < m_command.display) - { - ::Sleep(250); - } - - SetState(WIXSTDBA_STATE_APPLIED, hrStatus); - SetTaskbarButtonProgress(100); // show full progress bar, green, yellow, or red - - // If we successfully applied an update close the window since the new Bundle should be running now. - if (SUCCEEDED(hrStatus) && m_fUpdating) - { - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Update downloaded, close bundle."); - ::PostMessageW(m_hWnd, WM_CLOSE, 0, 0); - } - - return IDNOACTION; - } - - -private: // privates - // - // UiThreadProc - entrypoint for UI thread. - // - static DWORD WINAPI UiThreadProc( - __in LPVOID pvContext - ) - { - HRESULT hr = S_OK; - CWixStandardBootstrapperApplication* pThis = (CWixStandardBootstrapperApplication*)pvContext; - BOOL fComInitialized = FALSE; - BOOL fRet = FALSE; - MSG msg = { }; - - // Initialize COM and theme. - hr = ::CoInitialize(NULL); - BalExitOnFailure(hr, "Failed to initialize COM."); - fComInitialized = TRUE; - - hr = ThemeInitialize(pThis->m_hModule); - BalExitOnFailure(hr, "Failed to initialize theme manager."); - - hr = pThis->InitializeData(); - BalExitOnFailure(hr, "Failed to initialize data in bootstrapper application."); - - // Create main window. - pThis->InitializeTaskbarButton(); - hr = pThis->CreateMainWindow(); - BalExitOnFailure(hr, "Failed to create main window."); - - // Okay, we're ready for packages now. - pThis->SetState(WIXSTDBA_STATE_INITIALIZED, hr); - ::PostMessageW(pThis->m_hWnd, BOOTSTRAPPER_ACTION_HELP == pThis->m_command.action ? WM_WIXSTDBA_SHOW_HELP : WM_WIXSTDBA_DETECT_PACKAGES, 0, 0); - - // message pump - while (0 != (fRet = ::GetMessageW(&msg, NULL, 0, 0))) - { - if (-1 == fRet) - { - hr = E_UNEXPECTED; - BalExitOnFailure(hr, "Unexpected return value from message pump."); - } - else if (!ThemeHandleKeyboardMessage(pThis->m_pTheme, msg.hwnd, &msg)) - { - ::TranslateMessage(&msg); - ::DispatchMessageW(&msg); - } - } - - // Succeeded thus far, check to see if anything went wrong while actually - // executing changes. - if (FAILED(pThis->m_hrFinal)) - { - hr = pThis->m_hrFinal; - } - else if (pThis->CheckCanceled()) - { - hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT); - } - -LExit: - // destroy main window - pThis->DestroyMainWindow(); - - // initiate engine shutdown - DWORD dwQuit = HRESULT_CODE(hr); - if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == pThis->m_restartResult) - { - dwQuit = ERROR_SUCCESS_REBOOT_INITIATED; - } - else if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == pThis->m_restartResult) - { - dwQuit = ERROR_SUCCESS_REBOOT_REQUIRED; - } - pThis->m_pEngine->Quit(dwQuit); - - ReleaseTheme(pThis->m_pTheme); - ThemeUninitialize(); - - // uninitialize COM - if (fComInitialized) - { - ::CoUninitialize(); - } - - return hr; - } - - - static DWORD WINAPI ThreadProc( - __in LPVOID pvContext - ) - { - CWixStandardBootstrapperApplication* pThis = static_cast(pvContext);; - - HRESULT hr = S_OK; - IXMLDOMDocument *pixd = NULL; - IXMLDOMNode* pNode = NULL; - LPWSTR sczUpdateUrl = NULL; - DWORD64 qwSize = 0; - - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Checking for update."); - - // Load the update XML from a location url and parse it for an update. - // - // - // - // - // - - hr = XmlLoadDocumentFromFile(pThis->m_wzUpdateLocation, &pixd); - BalExitOnFailure(hr, "Failed to load version check XML document."); - - hr = XmlSelectSingleNode(pixd, L"/Setup/Upgrade", &pNode); - BalExitOnFailure(hr, "Failed to select upgrade node."); - - if (S_OK == hr) - { - hr = XmlGetAttributeEx(pNode, L"Url", &sczUpdateUrl); - BalExitOnFailure(hr, "Failed to get url attribute."); - - hr = XmlGetAttributeLargeNumber(pNode, L"Size", &qwSize); - } - - if (sczUpdateUrl && *sczUpdateUrl) - { - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Update available, url: %ls; size: %I64u.", sczUpdateUrl, qwSize); - // Show upgrade on install and modify pages - if (pThis->m_rgdwPageIds[WIXSTDBA_PAGE_INSTALL] == pThis->m_dwCurrentPage || - pThis->m_rgdwPageIds[WIXSTDBA_PAGE_MODIFY] == pThis->m_dwCurrentPage) - { - pThis->m_pEngine->SetUpdate(NULL, sczUpdateUrl, qwSize, BOOTSTRAPPER_UPDATE_HASH_TYPE_NONE, NULL, 0); - ThemeControlEnable(pThis->m_pTheme, WIXSTDBA_CONTROL_UPGRADE_LINK, TRUE); - } - } - else - { - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "No update available."); - } - -LExit: - ReleaseObject(pixd); - ReleaseObject(pNode); - ReleaseStr(sczUpdateUrl); - - return 0; - } - - - // - // InitializeData - initializes all the package and prereq information. - // - HRESULT InitializeData() - { - HRESULT hr = S_OK; - LPWSTR sczModulePath = NULL; - IXMLDOMDocument *pixdManifest = NULL; - - hr = BalManifestLoad(m_hModule, &pixdManifest); - BalExitOnFailure(hr, "Failed to load bootstrapper application manifest."); - - hr = ParseOverridableVariablesFromXml(pixdManifest); - BalExitOnFailure(hr, "Failed to read overridable variables."); - - hr = ProcessCommandLine(&m_sczLanguage); - ExitOnFailure(hr, "Unknown commandline parameters."); - - // Override default language to correctly support UK English (this is not required in WiX 3.8) - if (!(m_sczLanguage && *m_sczLanguage)) - { - hr = StrAllocFormatted(&m_sczLanguage, L"%u", ::GetUserDefaultLangID()); - BalExitOnFailure(hr, "Failed to set language."); - } - - hr = PathRelativeToModule(&sczModulePath, NULL, m_hModule); - BalExitOnFailure(hr, "Failed to get module path."); - - hr = LoadLocalization(sczModulePath, m_sczLanguage); - ExitOnFailure(hr, "Failed to load localization."); - - hr = LoadTheme(sczModulePath, m_sczLanguage); - ExitOnFailure(hr, "Failed to load theme."); - - hr = BalInfoParseFromXml(&m_Bundle, pixdManifest); - BalExitOnFailure(hr, "Failed to load bundle information."); - - hr = BalConditionsParseFromXml(&m_Conditions, pixdManifest, m_pWixLoc); - BalExitOnFailure(hr, "Failed to load conditions from XML."); - - LoadBootstrapperBAFunctions(); - - hr = ParseBootrapperApplicationDataFromXml(pixdManifest); - BalExitOnFailure(hr, "Failed to read bootstrapper application data."); - - LOC_STRING* pLocString = NULL; - LocGetString(m_pWixLoc, L"#(loc.ProgressHeader)", &pLocString); - m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_PROGRESS_HEADER, pLocString->wzText); - LocGetString(m_pWixLoc, L"#(loc.ProgressInfo)", &pLocString); - m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_PROGRESS_INFO, pLocString->wzText); - LocGetString(m_pWixLoc, L"#(loc.SuccessHeader)", &pLocString); - m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_SUCCESS_HEADER, pLocString->wzText); - LocGetString(m_pWixLoc, L"#(loc.SuccessInfo)", &pLocString); - m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_SUCCESS_INFO, pLocString->wzText); - LocGetString(m_pWixLoc, L"#(loc.FailureHeader)", &pLocString); - m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_FAILURE_HEADER, pLocString->wzText); - if (m_fPrereq) - { - hr = ParsePrerequisiteInformationFromXml(pixdManifest); - BalExitOnFailure(hr, "Failed to read prerequisite information."); - } - else - { - hr = ParseBootrapperApplicationDataFromXml(pixdManifest); - BalExitOnFailure(hr, "Failed to read bootstrapper application data."); - } - - -LExit: - ReleaseObject(pixdManifest); - ReleaseStr(sczModulePath); - - return hr; - } - - - // - // ProcessCommandLine - process the provided command line arguments. - // - HRESULT ProcessCommandLine( - __inout LPWSTR* psczLanguage - ) - { - HRESULT hr = S_OK; - int argc = 0; - LPWSTR* argv = NULL; - LPWSTR sczVariableName = NULL; - LPWSTR sczVariableValue = NULL; - - if (m_command.wzCommandLine && *m_command.wzCommandLine) - { - argv = ::CommandLineToArgvW(m_command.wzCommandLine, &argc); - ExitOnNullWithLastError(argv, hr, "Failed to get command line."); - - for (int i = 0; i < argc; ++i) - { - if (argv[i][0] == L'-' || argv[i][0] == L'/') - { - if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"lang", -1)) - { - if (i + 1 >= argc) - { - hr = E_INVALIDARG; - BalExitOnFailure(hr, "Must specify a language."); - } - - ++i; - - hr = StrAllocString(psczLanguage, &argv[i][0], 0); - BalExitOnFailure(hr, "Failed to copy language."); - } - } - else if (m_sdOverridableVariables) - { - const wchar_t* pwc = wcschr(argv[i], L'='); - if (pwc) - { - hr = StrAllocString(&sczVariableName, argv[i], pwc - argv[i]); - BalExitOnFailure(hr, "Failed to copy variable name."); - - hr = DictKeyExists(m_sdOverridableVariables, sczVariableName); - if (E_NOTFOUND == hr) - { - BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Ignoring attempt to set non-overridable variable: '%ls'.", sczVariableName); - hr = S_OK; - continue; - } - ExitOnFailure(hr, "Failed to check the dictionary of overridable variables."); - - hr = StrAllocString(&sczVariableValue, ++pwc, 0); - BalExitOnFailure(hr, "Failed to copy variable value."); - - hr = m_pEngine->SetVariableString(sczVariableName, sczVariableValue); - BalExitOnFailure(hr, "Failed to set variable."); - } - else - { - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Ignoring unknown argument: %ls", argv[i]); - } - } - } - } - -LExit: - if (argv) - { - ::LocalFree(argv); - } - - ReleaseStr(sczVariableName); - ReleaseStr(sczVariableValue); - - return hr; - } - - HRESULT LoadLocalization( - __in_z LPCWSTR wzModulePath, - __in_z_opt LPCWSTR wzLanguage - ) - { - HRESULT hr = S_OK; - LPWSTR sczLocPath = NULL; - LPCWSTR wzLocFileName = L"thm.wxl"; - - hr = LocProbeForFile(wzModulePath, wzLocFileName, wzLanguage, &sczLocPath); - BalExitOnFailure2(hr, "Failed to probe for loc file: %ls in path: %ls", wzLocFileName, wzModulePath); - - hr = LocLoadFromFile(sczLocPath, &m_pWixLoc); - BalExitOnFailure1(hr, "Failed to load loc file from path: %ls", sczLocPath); - - if (WIX_LOCALIZATION_LANGUAGE_NOT_SET != m_pWixLoc->dwLangId) - { - ::SetThreadLocale(m_pWixLoc->dwLangId); - } - - hr = StrAllocString(&m_sczConfirmCloseMessage, L"#(loc.ConfirmCancelMessage)", 0); - ExitOnFailure(hr, "Failed to initialize confirm message loc identifier."); - - hr = LocLocalizeString(m_pWixLoc, &m_sczConfirmCloseMessage); - BalExitOnFailure1(hr, "Failed to localize confirm close message: %ls", m_sczConfirmCloseMessage); - -LExit: - ReleaseStr(sczLocPath); - - return hr; - } - - - HRESULT LoadTheme( - __in_z LPCWSTR wzModulePath, - __in_z_opt LPCWSTR wzLanguage - ) - { - HRESULT hr = S_OK; - LPWSTR sczThemePath = NULL; - LPCWSTR wzThemeFileName = L"thm.xml"; - LPWSTR sczCaption = NULL; - - hr = LocProbeForFile(wzModulePath, wzThemeFileName, wzLanguage, &sczThemePath); - BalExitOnFailure2(hr, "Failed to probe for theme file: %ls in path: %ls", wzThemeFileName, wzModulePath); - - hr = ThemeLoadFromFile(sczThemePath, &m_pTheme); - BalExitOnFailure1(hr, "Failed to load theme from path: %ls", sczThemePath); - - hr = ThemeLocalize(m_pTheme, m_pWixLoc); - BalExitOnFailure1(hr, "Failed to localize theme: %ls", sczThemePath); - - // Update the caption if there are any formatted strings in it. - hr = BalFormatString(m_pTheme->sczCaption, &sczCaption); - if (SUCCEEDED(hr)) - { - ThemeUpdateCaption(m_pTheme, sczCaption); - } - -LExit: - ReleaseStr(sczCaption); - ReleaseStr(sczThemePath); - - return hr; - } - - - HRESULT ParseOverridableVariablesFromXml( - __in IXMLDOMDocument* pixdManifest - ) - { - HRESULT hr = S_OK; - IXMLDOMNode* pNode = NULL; - IXMLDOMNodeList* pNodes = NULL; - DWORD cNodes = 0; - LPWSTR scz = NULL; - - // get the list of variables users can override on the command line - hr = XmlSelectNodes(pixdManifest, L"/BootstrapperApplicationData/WixStdbaOverridableVariable", &pNodes); - if (S_FALSE == hr) - { - ExitFunction1(hr = S_OK); - } - ExitOnFailure(hr, "Failed to select overridable variable nodes."); - - hr = pNodes->get_length((long*)&cNodes); - ExitOnFailure(hr, "Failed to get overridable variable node count."); - - if (cNodes) - { - hr = DictCreateStringList(&m_sdOverridableVariables, 32, DICT_FLAG_NONE); - ExitOnFailure(hr, "Failed to create the string dictionary."); - - for (DWORD i = 0; i < cNodes; ++i) - { - hr = XmlNextElement(pNodes, &pNode, NULL); - ExitOnFailure(hr, "Failed to get next node."); - - // @Name - hr = XmlGetAttributeEx(pNode, L"Name", &scz); - ExitOnFailure(hr, "Failed to get @Name."); - - hr = DictAddKey(m_sdOverridableVariables, scz); - ExitOnFailure1(hr, "Failed to add \"%ls\" to the string dictionary.", scz); - - // prepare next iteration - ReleaseNullObject(pNode); - } - } - -LExit: - ReleaseObject(pNode); - ReleaseObject(pNodes); - ReleaseStr(scz); - return hr; - } - - - HRESULT ParsePrerequisiteInformationFromXml( - __in IXMLDOMDocument* pixdManifest - ) - { - HRESULT hr = S_OK; - IXMLDOMNode* pNode = NULL; - - hr = XmlSelectSingleNode(pixdManifest, L"/BootstrapperApplicationData/WixMbaPrereqInformation", &pNode); - if (S_FALSE == hr) - { - hr = E_INVALIDARG; - } - BalExitOnFailure(hr, "BootstrapperApplication.xml manifest is missing prerequisite information."); - - hr = XmlGetAttributeEx(pNode, L"PackageId", &m_sczPrereqPackage); - BalExitOnFailure(hr, "Failed to get prerequisite package identifier."); - - hr = XmlGetAttributeEx(pNode, L"LicenseUrl", &m_sczLicenseUrl); - if (E_NOTFOUND == hr) - { - hr = S_OK; - } - BalExitOnFailure(hr, "Failed to get prerequisite license URL."); - - hr = XmlGetAttributeEx(pNode, L"LicenseFile", &m_sczLicenseFile); - if (E_NOTFOUND == hr) - { - hr = S_OK; - } - BalExitOnFailure(hr, "Failed to get prerequisite license file."); - -LExit: - ReleaseObject(pNode); - return hr; - } - - - HRESULT ParseBootrapperApplicationDataFromXml( - __in IXMLDOMDocument* pixdManifest - ) - { - HRESULT hr = S_OK; - IXMLDOMNode* pNode = NULL; - DWORD dwBool = 0; - - hr = XmlSelectSingleNode(pixdManifest, L"/BootstrapperApplicationData/WixExtbaInformation", &pNode); - if (S_FALSE == hr) - { - hr = E_INVALIDARG; - } - BalExitOnFailure(hr, "BootstrapperApplication.xml manifest is missing wixextba information."); - - hr = XmlGetAttributeEx(pNode, L"LicenseFile", &m_sczLicenseFile); - if (E_NOTFOUND == hr) - { - hr = S_OK; - } - BalExitOnFailure(hr, "Failed to get license file."); - - hr = XmlGetAttributeEx(pNode, L"LicenseUrl", &m_sczLicenseUrl); - if (E_NOTFOUND == hr) - { - hr = S_OK; - } - BalExitOnFailure(hr, "Failed to get license URL."); - - ReleaseObject(pNode); - - hr = XmlSelectSingleNode(pixdManifest, L"/BootstrapperApplicationData/WixExtbaOptions", &pNode); - if (S_FALSE == hr) - { - ExitFunction1(hr = S_OK); - } - BalExitOnFailure(hr, "Failed to read wixextba options from BootstrapperApplication.xml manifest."); - - hr = XmlGetAttributeNumber(pNode, L"SuppressOptionsUI", &dwBool); - if (E_NOTFOUND == hr) - { - hr = S_OK; - } - else if (SUCCEEDED(hr)) - { - m_fSuppressOptionsUI = 0 < dwBool; - } - BalExitOnFailure(hr, "Failed to get SuppressOptionsUI value."); - - dwBool = 0; - hr = XmlGetAttributeNumber(pNode, L"SuppressDowngradeFailure", &dwBool); - if (E_NOTFOUND == hr) - { - hr = S_OK; - } - else if (SUCCEEDED(hr)) - { - m_fSuppressDowngradeFailure = 0 < dwBool; - } - BalExitOnFailure(hr, "Failed to get SuppressDowngradeFailure value."); - - dwBool = 0; - hr = XmlGetAttributeNumber(pNode, L"SuppressRepair", &dwBool); - if (E_NOTFOUND == hr) - { - hr = S_OK; - } - else if (SUCCEEDED(hr)) - { - m_fSuppressRepair = 0 < dwBool; - } - BalExitOnFailure(hr, "Failed to get SuppressRepair value."); - - hr = XmlGetAttributeNumber(pNode, L"ShowVersion", &dwBool); - if (E_NOTFOUND == hr) - { - hr = S_OK; - } - else if (SUCCEEDED(hr)) - { - m_fShowVersion = 0 < dwBool; - } - BalExitOnFailure(hr, "Failed to get ShowVersion value."); - -LExit: - ReleaseObject(pNode); - return hr; - } - - - // - // CreateMainWindow - creates the main install window. - // - HRESULT CreateMainWindow() - { - HRESULT hr = S_OK; - HICON hIcon = reinterpret_cast(m_pTheme->hIcon); - WNDCLASSW wc = { }; - DWORD dwWindowStyle = 0; - int x = CW_USEDEFAULT; - int y = CW_USEDEFAULT; - POINT ptCursor = { }; - HMONITOR hMonitor = NULL; - MONITORINFO mi = { }; - - // If the theme did not provide an icon, try using the icon from the bundle engine. - if (!hIcon) - { - HMODULE hBootstrapperEngine = ::GetModuleHandleW(NULL); - if (hBootstrapperEngine) - { - hIcon = ::LoadIconW(hBootstrapperEngine, MAKEINTRESOURCEW(1)); - } - } - - // Register the window class and create the window. - wc.lpfnWndProc = CWixStandardBootstrapperApplication::WndProc; - wc.hInstance = m_hModule; - wc.hIcon = hIcon; - wc.hCursor = ::LoadCursorW(NULL, (LPCWSTR)IDC_ARROW); - wc.hbrBackground = m_pTheme->rgFonts[m_pTheme->dwFontId].hBackground; - wc.lpszMenuName = NULL; - wc.lpszClassName = WIXSTDBA_WINDOW_CLASS; - if (!::RegisterClassW(&wc)) - { - ExitWithLastError(hr, "Failed to register window."); - } - - m_fRegistered = TRUE; - - // Calculate the window style based on the theme style and command display value. - dwWindowStyle = m_pTheme->dwStyle; - if (BOOTSTRAPPER_DISPLAY_NONE >= m_command.display) - { - dwWindowStyle &= ~WS_VISIBLE; - } - - // Don't show the window if there is a splash screen (it will be made visible when the splash screen is hidden) - if (::IsWindow(m_command.hwndSplashScreen)) - { - dwWindowStyle &= ~WS_VISIBLE; - } - - // Center the window on the monitor with the mouse. - if (::GetCursorPos(&ptCursor)) - { - hMonitor = ::MonitorFromPoint(ptCursor, MONITOR_DEFAULTTONEAREST); - if (hMonitor) - { - mi.cbSize = sizeof(mi); - if (::GetMonitorInfoW(hMonitor, &mi)) - { - x = mi.rcWork.left + (mi.rcWork.right - mi.rcWork.left - m_pTheme->nWidth) / 2; - y = mi.rcWork.top + (mi.rcWork.bottom - mi.rcWork.top - m_pTheme->nHeight) / 2; - } - } - } - - m_hWnd = ::CreateWindowExW(0, wc.lpszClassName, m_pTheme->sczCaption, dwWindowStyle, x, y, m_pTheme->nWidth, m_pTheme->nHeight, HWND_DESKTOP, NULL, m_hModule, this); - ExitOnNullWithLastError(m_hWnd, hr, "Failed to create window."); - - hr = S_OK; - -LExit: - return hr; - } - - - // - // InitializeTaskbarButton - initializes taskbar button for progress. - // - void InitializeTaskbarButton() - { - HRESULT hr = S_OK; - - hr = ::CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_ALL, __uuidof(ITaskbarList3), reinterpret_cast(&m_pTaskbarList)); - if (REGDB_E_CLASSNOTREG == hr) // not supported before Windows 7 - { - ExitFunction1(hr = S_OK); - } - BalExitOnFailure(hr, "Failed to create ITaskbarList3. Continuing."); - - m_uTaskbarButtonCreatedMessage = ::RegisterWindowMessageW(L"TaskbarButtonCreated"); - BalExitOnNullWithLastError(m_uTaskbarButtonCreatedMessage, hr, "Failed to get TaskbarButtonCreated message. Continuing."); - -LExit: - return; - } - - // - // DestroyMainWindow - clean up all the window registration. - // - void DestroyMainWindow() - { - if (::IsWindow(m_hWnd)) - { - ::DestroyWindow(m_hWnd); - m_hWnd = NULL; - m_fTaskbarButtonOK = FALSE; - } - - if (m_fRegistered) - { - ::UnregisterClassW(WIXSTDBA_WINDOW_CLASS, m_hModule); - m_fRegistered = FALSE; - } - } - - - // - // WndProc - standard windows message handler. - // - static LRESULT CALLBACK WndProc( - __in HWND hWnd, - __in UINT uMsg, - __in WPARAM wParam, - __in LPARAM lParam - ) - { -#pragma warning(suppress:4312) - CWixStandardBootstrapperApplication* pBA = reinterpret_cast(::GetWindowLongPtrW(hWnd, GWLP_USERDATA)); - - switch (uMsg) - { - case WM_NCCREATE: - { - LPCREATESTRUCT lpcs = reinterpret_cast(lParam); - pBA = reinterpret_cast(lpcs->lpCreateParams); -#pragma warning(suppress:4244) - ::SetWindowLongPtrW(hWnd, GWLP_USERDATA, reinterpret_cast(pBA)); - } - break; - - case WM_NCDESTROY: - { - LRESULT lres = ThemeDefWindowProc(pBA ? pBA->m_pTheme : NULL, hWnd, uMsg, wParam, lParam); - ::SetWindowLongPtrW(hWnd, GWLP_USERDATA, 0); - return lres; - } - - case WM_CREATE: - if (!pBA->OnCreate(hWnd)) - { - return -1; - } - break; - - case WM_QUERYENDSESSION: - return IDCANCEL != pBA->OnSystemShutdown(static_cast(lParam), IDCANCEL); - - case WM_CLOSE: - // If the user chose not to close, do *not* let the default window proc handle the message. - if (!pBA->OnClose()) - { - return 0; - } - break; - - case WM_DESTROY: - ::PostQuitMessage(0); - break; - - case WM_WIXSTDBA_SHOW_HELP: - pBA->OnShowHelp(); - return 0; - - case WM_WIXSTDBA_DETECT_PACKAGES: - pBA->OnDetect(); - return 0; - - case WM_WIXSTDBA_PLAN_PACKAGES: - pBA->OnPlan(static_cast(lParam)); - return 0; - - case WM_WIXSTDBA_APPLY_PACKAGES: - pBA->OnApply(); - return 0; - - case WM_WIXSTDBA_CHANGE_STATE: - pBA->OnChangeState(static_cast(lParam)); - return 0; - - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX: - pBA->OnClickAcceptCheckbox(); - return 0; - - case WIXSTDBA_CONTROL_PERMACHINE_RADIO: __fallthrough; - case WIXSTDBA_CONTROL_PERUSER_RADIO: - pBA->OnClickInstallScope(); - return 0; - - case WIXSTDBA_CONTROL_REGSIGNIN_RADIO: __fallthrough; - case WIXSTDBA_CONTROL_REGCREATE_RADIO: __fallthrough; - case WIXSTDBA_CONTROL_SKIPREG_CHECKBOX: - pBA->OnClickSkipRegistrationCheckbox(); - return 0; - - - case WIXSTDBA_CONTROL_OPTIONS_BUTTON: - pBA->OnClickOptionsButton(); - return 0; - - case WIXSTDBA_CONTROL_BROWSE_BUTTON: - pBA->OnClickOptionsBrowseButton(WIXSTDBA_CONTROL_BROWSE_BUTTON); - return 0; - - case WIXSTDBA_CONTROL_OK_BUTTON: - pBA->OnClickOptionsOkButton(); - return 0; - - case WIXSTDBA_CONTROL_CANCEL_BUTTON: - pBA->OnClickOptionsCancelButton(); - return 0; - - case WIXSTDBA_CONTROL_INSTALL_BUTTON: - pBA->OnClickInstallButton(); - return 0; - - case WIXSTDBA_CONTROL_REPAIR_BUTTON: - pBA->OnClickRepairButton(); - return 0; - - case WIXSTDBA_CONTROL_UNINSTALL_BUTTON: - pBA->OnClickUninstallButton(); - return 0; - - case WIXSTDBA_CONTROL_LAUNCH_BUTTON: - pBA->OnClickLaunchButton(); - return 0; - - case WIXSTDBA_CONTROL_SUCCESS_RESTART_BUTTON: __fallthrough; - case WIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON: - pBA->OnClickRestartButton(); - return 0; - - case WIXSTDBA_CONTROL_HELP_CANCEL_BUTTON: __fallthrough; - - case WIXSTDBA_CONTROL_WELCOME_CANCEL_BUTTON: __fallthrough; - case WIXSTDBA_CONTROL_MODIFY_CANCEL_BUTTON: __fallthrough; - case WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON: __fallthrough; - case WIXSTDBA_CONTROL_SUCCESS_CANCEL_BUTTON: __fallthrough; - case WIXSTDBA_CONTROL_FAILURE_CANCEL_BUTTON: __fallthrough; - case WIXSTDBA_CONTROL_CLOSE_BUTTON: - pBA->OnClickCloseButton(); - return 0; - case WIXSTDBA_CONTROL_NEXT_BUTTON: - pBA->OnClickNextButton(); - return 0; - case WIXSTDBA_CONTROL_BACK_BUTTON: - pBA->OnClickBackButton(); - return 0; - - } - break; - - case WM_NOTIFY: - if (lParam) - { - LPNMHDR pnmhdr = reinterpret_cast(lParam); - switch (pnmhdr->code) - { - case NM_CLICK: __fallthrough; - case NM_RETURN: - switch (static_cast(pnmhdr->idFrom)) - { - case WIXSTDBA_CONTROL_EULA_LINK: - pBA->OnClickEulaLink(); - return 1; - case WIXSTDBA_CONTROL_FAILURE_LOGFILE_LINK: - pBA->OnClickLogFileLink(); - return 1; - case WIXSTDBA_CONTROL_UPGRADE_LINK: - pBA->OnClickUpgradeLink(); - return 1; - } - } - } - break; - } - - if (pBA && pBA->m_pTaskbarList && uMsg == pBA->m_uTaskbarButtonCreatedMessage) - { - pBA->m_fTaskbarButtonOK = TRUE; - return 0; - } - - return ThemeDefWindowProc(pBA ? pBA->m_pTheme : NULL, hWnd, uMsg, wParam, lParam); - } - - - // - // OnCreate - finishes loading the theme. - // - BOOL OnCreate( - __in HWND hWnd - ) - { - HRESULT hr = S_OK; - LPWSTR sczText = NULL; - LPWSTR sczLicenseFormatted = NULL; - LPWSTR sczLicensePath = NULL; - LPWSTR sczLicenseDirectory = NULL; - LPWSTR sczLicenseFilename = NULL; - - hr = ThemeLoadControls(m_pTheme, hWnd, vrgInitControls, countof(vrgInitControls)); - BalExitOnFailure(hr, "Failed to load theme controls."); - - C_ASSERT(COUNT_WIXSTDBA_PAGE == countof(vrgwzPageNames)); - C_ASSERT(countof(m_rgdwPageIds) == countof(vrgwzPageNames)); - - ThemeGetPageIds(m_pTheme, vrgwzPageNames, m_rgdwPageIds, countof(m_rgdwPageIds)); - - // Initialize the text on all "application" (non-page) controls. - for (DWORD i = 0; i < m_pTheme->cControls; ++i) - { - THEME_CONTROL* pControl = m_pTheme->rgControls + i; - if (!pControl->wPageId && pControl->sczText && *pControl->sczText) - { - HRESULT hrFormat = BalFormatString(pControl->sczText, &sczText); - if (SUCCEEDED(hrFormat)) - { - ThemeSetTextControl(m_pTheme, pControl->wId, sczText); - } - } - } - - // Load the RTF EULA control with text if the control exists. - if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_EULA_RICHEDIT)) - { - hr = (m_sczLicenseFile && *m_sczLicenseFile) ? S_OK : E_INVALIDDATA; - if (SUCCEEDED(hr)) - { - hr = StrAllocString(&sczLicenseFormatted, m_sczLicenseFile, 0); - if (SUCCEEDED(hr)) - { - hr = LocLocalizeString(m_pWixLoc, &sczLicenseFormatted); - if (SUCCEEDED(hr)) - { - hr = BalFormatString(sczLicenseFormatted, &sczLicenseFormatted); - if (SUCCEEDED(hr)) - { - hr = PathRelativeToModule(&sczLicensePath, sczLicenseFormatted, m_hModule); - if (SUCCEEDED(hr)) - { - hr = PathGetDirectory(sczLicensePath, &sczLicenseDirectory); - if (SUCCEEDED(hr)) - { - hr = StrAllocString(&sczLicenseFilename, PathFile(sczLicenseFormatted), 0); - if (SUCCEEDED(hr)) - { - hr = LocProbeForFile(sczLicenseDirectory, sczLicenseFilename, m_sczLanguage, &sczLicensePath); - if (SUCCEEDED(hr)) - { - hr = ThemeLoadRichEditFromFile(m_pTheme, WIXSTDBA_CONTROL_EULA_RICHEDIT, sczLicensePath, m_hModule); - } - } - } - } - } - } - } - } - - if (FAILED(hr)) - { - BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Failed to load file into license richedit control from path '%ls' manifest value: %ls", sczLicensePath, m_sczLicenseFile); - hr = S_OK; - } - } - -LExit: - ReleaseStr(sczLicenseFilename); - ReleaseStr(sczLicenseDirectory); - ReleaseStr(sczLicensePath); - ReleaseStr(sczLicenseFormatted); - ReleaseStr(sczText); - - return SUCCEEDED(hr); - } - - - // - // OnShowHelp - display the help page. - // - void OnShowHelp() - { - SetState(WIXSTDBA_STATE_HELP, S_OK); - - // If the UI should be visible, display it now and hide the splash screen - if (BOOTSTRAPPER_DISPLAY_NONE < m_command.display) - { - ::ShowWindow(m_pTheme->hwndParent, SW_SHOW); - } - - m_pEngine->CloseSplashScreen(); - - return; - } - - - // - // OnDetect - start the processing of packages. - // - void OnDetect() - { - HRESULT hr = S_OK; - - if (m_pBAFunction) - { - hr = m_pBAFunction->OnDetect(); - BalExitOnFailure(hr, "Failed calling detect BA function."); - } - - SetState(WIXSTDBA_STATE_DETECTING, hr); - - // If the UI should be visible, display it now and hide the splash screen - if (BOOTSTRAPPER_DISPLAY_NONE < m_command.display) - { - ::ShowWindow(m_pTheme->hwndParent, SW_SHOW); - } - - m_pEngine->CloseSplashScreen(); - - // Tell the core we're ready for the packages to be processed now. - hr = m_pEngine->Detect(); - BalExitOnFailure(hr, "Failed to start detecting chain."); - -LExit: - if (FAILED(hr)) - { - SetState(WIXSTDBA_STATE_DETECTING, hr); - } - - return; - } - - - // - // OnPlan - plan the detected changes. - // - void OnPlan( - __in BOOTSTRAPPER_ACTION action - ) - { - HRESULT hr = S_OK; - - m_plannedAction = action; - - LOC_STRING* pLocString = NULL; - - if (m_plannedAction == BOOTSTRAPPER_ACTION_UNINSTALL) - { - m_fIsUninstall = TRUE; - LocGetString(m_pWixLoc, L"#(loc.ProgressHeaderUninstall)", &pLocString); - m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_PROGRESS_HEADER, pLocString->wzText); - LocGetString(m_pWixLoc, L"#(loc.ProgressInfoUninstall)", &pLocString); - m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_PROGRESS_INFO, pLocString->wzText); - } - - if (m_plannedAction == BOOTSTRAPPER_ACTION_REPAIR) - { - m_fIsRepair = TRUE; - LocGetString(m_pWixLoc, L"#(loc.ProgressHeaderRepair)", &pLocString); - m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_PROGRESS_HEADER, pLocString->wzText); - LocGetString(m_pWixLoc, L"#(loc.ProgressInfoRepair)", &pLocString); - m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_PROGRESS_INFO, pLocString->wzText); - } - - // If we are going to apply a downgrade, bail. - if (m_fDowngrading && BOOTSTRAPPER_ACTION_UNINSTALL < action) - { - if (m_fSuppressDowngradeFailure) - { - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "A newer version of this product is installed but downgrade failure has been suppressed; continuing..."); - } - else - { - hr = HRESULT_FROM_WIN32(ERROR_PRODUCT_VERSION); - BalExitOnFailure(hr, "Cannot install a product when a newer version is installed."); - } - } - - SetState(WIXSTDBA_STATE_PLANNING, hr); - - if (m_pBAFunction) - { - m_pBAFunction->OnPlan(); - } - - hr = m_pEngine->Plan(action); - BalExitOnFailure(hr, "Failed to start planning packages."); - -LExit: - if (FAILED(hr)) - { - SetState(WIXSTDBA_STATE_PLANNING, hr); - } - - return; - } - - - // - // OnApply - apply the packages. - // - void OnApply() - { - HRESULT hr = S_OK; - - SetState(WIXSTDBA_STATE_APPLYING, hr); - SetProgressState(hr); - SetTaskbarButtonProgress(0); - - hr = m_pEngine->Apply(m_hWnd); - BalExitOnFailure(hr, "Failed to start applying packages."); - - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, TRUE); // ensure the cancel button is enabled before starting. - -LExit: - if (FAILED(hr)) - { - SetState(WIXSTDBA_STATE_APPLYING, hr); - } - - return; - } - - - // - // OnChangeState - change state. - // - void OnChangeState( - __in WIXSTDBA_STATE state - ) - { - WIXSTDBA_STATE stateOld = m_state; - DWORD dwOldPageId = 0; - DWORD dwNewPageId = 0; - LPWSTR sczText = NULL; - LPWSTR sczUnformattedText = NULL; - LPWSTR sczControlState = NULL; - LPWSTR sczControlName = NULL; - LOC_STRING* pLocString = NULL; - m_state = state; - - // If our install is at the end (success or failure) and we're not showing full UI or - // we successfully installed the prerequisite then exit (prompt for restart if required). - if ((WIXSTDBA_STATE_APPLIED <= m_state && BOOTSTRAPPER_DISPLAY_FULL > m_command.display) || - (WIXSTDBA_STATE_APPLIED == m_state && m_fPrereq)) - { - // If a restart was required but we were not automatically allowed to - // accept the reboot then do the prompt. - if (m_fRestartRequired && !m_fAllowRestart) - { - StrAllocFromError(&sczUnformattedText, HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED), NULL); - - int nResult = ::MessageBoxW(m_hWnd, sczUnformattedText ? sczUnformattedText : L"The requested operation is successful. Changes will not be effective until the system is rebooted.", m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OKCANCEL); - m_fAllowRestart = (IDOK == nResult); - } - - // Quietly exit. - ::PostMessageW(m_hWnd, WM_CLOSE, 0, 0); - } - else // try to change the pages. - { - DeterminePageId(stateOld, &dwOldPageId); - DeterminePageId(m_state, &dwNewPageId); - - if (dwOldPageId != dwNewPageId) - { - // Enable disable controls per-page. - if (m_rgdwPageIds[WIXSTDBA_PAGE_INSTALL] == dwNewPageId) // on the "Install" page, ensure the install button is enabled/disabled correctly. - { - LONGLONG llElevated = 0; - if (m_Bundle.fPerMachine) - { - BalGetNumericVariable(WIXBUNDLE_VARIABLE_ELEVATED, &llElevated); - } - ThemeControlElevates(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, (m_Bundle.fPerMachine && !llElevated)); - - // If the EULA control exists, show it only if a license URL is provided as well. - if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_EULA_LINK)) - { - BOOL fEulaLink = (m_sczLicenseUrl && *m_sczLicenseUrl); - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_EULA_LINK, fEulaLink); - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX, fEulaLink); - } - - BOOL fAcceptedLicense = !ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX) || !ThemeControlEnabled(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX) || ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX); - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, fAcceptedLicense); - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_NEXT_BUTTON, fAcceptedLicense); - - // If there is an "Options" page, the "Options" button exists, and it hasn't been suppressed, then enable the button. - BOOL fOptionsEnabled = m_rgdwPageIds[WIXSTDBA_PAGE_INSTALLDIR] && ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_OPTIONS_BUTTON) && !m_fSuppressOptionsUI; - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_OPTIONS_BUTTON, fOptionsEnabled); - - // Show/Hide the version label if it exists. - if (m_rgdwPageIds[WIXSTDBA_PAGE_INSTALLDIR] && ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_VERSION_LABEL) && !m_fShowVersion) - { - ThemeShowControl(m_pTheme, WIXSTDBA_CONTROL_VERSION_LABEL, SW_HIDE); - } - } - else if (m_rgdwPageIds[WIXSTDBA_PAGE_MODIFY] == dwNewPageId) - { - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_REPAIR_BUTTON, !m_fSuppressRepair); - } - else if (m_rgdwPageIds[WIXSTDBA_PAGE_INSTALLDIR] == dwNewPageId) - { - HRESULT hr = BalGetStringVariable(WIXSTDBA_VARIABLE_INSTALL_FOLDER, &sczUnformattedText); - if (SUCCEEDED(hr)) - { - BalFormatString(sczUnformattedText, &sczText); - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX, sczText); - } - } - else if (m_rgdwPageIds[WIXSTDBA_PAGE_SUCCESS] == dwNewPageId) // on the "Success" page, check if the restart or launch button should be enabled. - { - BOOL fShowRestartButton = FALSE; - BOOL fLaunchTargetExists = FALSE; - - if (m_fIsRepair) - { - LocGetString(m_pWixLoc, L"#(loc.SuccessHeaderRepair)", &pLocString); - m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_SUCCESS_HEADER, pLocString->wzText); - LocGetString(m_pWixLoc, L"#(loc.SuccessInfoRepair)", &pLocString); - m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_SUCCESS_INFO, pLocString->wzText); - } - else if (m_fIsUninstall) - { - LocGetString(m_pWixLoc, L"#(loc.SuccessHeaderUninstall)", &pLocString); - m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_SUCCESS_HEADER, pLocString->wzText); - LocGetString(m_pWixLoc, L"#(loc.SuccessInfoUninstall)", &pLocString); - m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_SUCCESS_INFO, pLocString->wzText); - } - else - { - m_fInstallSucceed = TRUE; - - // If we have left some kind of error message file from MSI the show that - if (BalStringVariableExists(L"MSICustomErrFile")) - { - LPWSTR sczUnFormatedErrFile = NULL; - LPWSTR sczErrFile = NULL; - LPWSTR sczSuccessErrMsg = NULL; - FILE_ENCODING feEncodingFound = FILE_ENCODING_UNSPECIFIED; - - BalGetStringVariable(L"MSICustomErrFile", &sczUnFormatedErrFile); - BalFormatString(sczUnFormatedErrFile, &sczErrFile); - - if (SUCCEEDED(FileToString(sczErrFile, &sczSuccessErrMsg, &feEncodingFound))) - { - LocGetString(m_pWixLoc, L"#(loc.SuccessErrorInfoText)", &pLocString); - m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_SUCCESS_ERRINF, pLocString->wzText); - m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_SUCCESS_ERRMSG, sczSuccessErrMsg); - FileEnsureDelete(sczErrFile); - } - } - } - - if (m_fRestartRequired) - { - if (BOOTSTRAPPER_RESTART_PROMPT == m_command.restart) - { - fShowRestartButton = TRUE; - } - } - else if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_LAUNCH_BUTTON)) - { - fLaunchTargetExists = BalStringVariableExists(WIXSTDBA_VARIABLE_LAUNCH_TARGET_PATH); - } - - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_LAUNCH_BUTTON, fLaunchTargetExists && BOOTSTRAPPER_ACTION_UNINSTALL < m_plannedAction); - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_SUCCESS_RESTART_TEXT, fShowRestartButton); - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_SUCCESS_RESTART_BUTTON, fShowRestartButton); - } - else if (m_rgdwPageIds[WIXSTDBA_PAGE_FAILURE] == dwNewPageId) // on the "Failure" page, show error message and check if the restart button should be enabled. - { - BOOL fShowLogLink = (m_Bundle.sczLogVariable && *m_Bundle.sczLogVariable); // if there is a log file variable then we'll assume the log file exists. - BOOL fShowErrorMessage = FALSE; - BOOL fShowRestartButton = FALSE; - - if (m_fIsRepair) - { - LocGetString(m_pWixLoc, L"#(loc.FailureHeaderRepair)", &pLocString); - m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_FAILURE_HEADER, pLocString->wzText); - } - - if (m_fIsUninstall) - { - LocGetString(m_pWixLoc, L"#(loc.FailureHeaderUninstall)", &pLocString); - m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_FAILURE_HEADER, pLocString->wzText); - } - if (FAILED(m_hrFinal)) - { - // If we know the failure message, use that. - if (m_sczFailedMessage && *m_sczFailedMessage) - { - StrAllocString(&sczUnformattedText, m_sczFailedMessage, 0); - } - else // try to get the error message from the error code. - { - StrAllocFromError(&sczUnformattedText, m_hrFinal, NULL); - if (!sczUnformattedText || !*sczUnformattedText) - { - StrAllocFromError(&sczUnformattedText, E_FAIL, NULL); - } - } - - StrAllocFormatted(&sczText, L"0x%08x - %ls", m_hrFinal, sczUnformattedText); - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_FAILURE_MESSAGE_TEXT, sczText); - fShowErrorMessage = TRUE; - } - - if (m_fRestartRequired) - { - if (BOOTSTRAPPER_RESTART_PROMPT == m_command.restart) - { - fShowRestartButton = TRUE; - } - } - - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_FAILURE_LOGFILE_LINK, fShowLogLink); - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_FAILURE_MESSAGE_TEXT, fShowErrorMessage); - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_FAILURE_RESTART_TEXT, fShowRestartButton); - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON, fShowRestartButton); - } - - // Hide the upgrade link - if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_UPGRADE_LINK)) - { - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_UPGRADE_LINK, FALSE); - } - - // Process each control for special handling in the new page. - THEME_PAGE* pPage = ThemeGetPage(m_pTheme, dwNewPageId); - if (pPage) - { - for (DWORD i = 0; i < pPage->cControlIndices; ++i) - { - THEME_CONTROL* pControl = m_pTheme->rgControls + pPage->rgdwControlIndices[i]; - - // If we are on the install, options or modify pages and this is a named control, try to set its default state. - if ((m_rgdwPageIds[WIXSTDBA_PAGE_INSTALL] == dwNewPageId || - m_rgdwPageIds[WIXSTDBA_PAGE_INSTALLDIR] == dwNewPageId || - m_rgdwPageIds[WIXSTDBA_PAGE_SVC_OPTIONS] == dwNewPageId || - m_rgdwPageIds[WIXSTDBA_PAGE_MODIFY] == dwNewPageId) && - pControl->sczName && *pControl->sczName) - { - // If this is a checkbox control, try to set its default state to the state of a matching named Burn variable. - if (THEME_CONTROL_TYPE_CHECKBOX == pControl->type && WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX != pControl->wId) - { - LONGLONG llValue = 0; - HRESULT hr = BalGetNumericVariable(pControl->sczName, &llValue); - - ThemeSendControlMessage(m_pTheme, pControl->wId, BM_SETCHECK, SUCCEEDED(hr) && llValue ? BST_CHECKED : BST_UNCHECKED, 0); - } - - // If this is a button control with the BS_AUTORADIOBUTTON style, try to set its default - // state to the state of a matching named Burn variable. - if (THEME_CONTROL_TYPE_BUTTON == pControl->type && (BS_AUTORADIOBUTTON == (BS_AUTORADIOBUTTON & pControl->dwStyle))) - { - LONGLONG llValue = 0; - HRESULT hr = BalGetNumericVariable(pControl->sczName, &llValue); - - // If the control value isn't set then disable it. - if (!SUCCEEDED(hr)) - { - ThemeControlEnable(m_pTheme, pControl->wId, FALSE); - } - else - { - ThemeSendControlMessage(m_pTheme, pControl->wId, BM_SETCHECK, SUCCEEDED(hr) && llValue ? BST_CHECKED : BST_UNCHECKED, 0); - } - } - - // Hide or disable controls based on the control name with 'State' appended - HRESULT hr = StrAllocFormatted(&sczControlName, L"%lsState", pControl->sczName); - if (SUCCEEDED(hr)) - { - hr = BalGetStringVariable(sczControlName, &sczControlState); - if (SUCCEEDED(hr) && sczControlState && *sczControlState) - { - if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, sczControlState, -1, L"disable", -1)) - { - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Disable control %ls", pControl->sczName); - ThemeControlEnable(m_pTheme, pControl->wId, FALSE); - } - else if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, sczControlState, -1, L"hide", -1)) - { - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Hide control %ls", pControl->sczName); - // TODO: This doesn't work - ThemeShowControl(m_pTheme, pControl->wId, SW_HIDE); - } - } - } - } - - // Format the text in each of the new page's controls (if they have any text). - if (pControl->sczText && *pControl->sczText) - { - HRESULT hr = BalFormatString(pControl->sczText, &sczText); - if (SUCCEEDED(hr)) - { - ThemeSetTextControl(m_pTheme, pControl->wId, sczText); - } - } - } - } - - ThemeShowPage(m_pTheme, dwOldPageId, SW_HIDE); - ThemeShowPage(m_pTheme, dwNewPageId, SW_SHOW); - - - // Remember current page - m_dwCurrentPage = dwNewPageId; - - // On the install page set the focus to the install button or the next enabled control if install is disabled - if (m_rgdwPageIds[WIXSTDBA_PAGE_INSTALL] == dwNewPageId) - { - HWND hwndFocus = ::GetDlgItem(m_pTheme->hwndParent, WIXSTDBA_CONTROL_INSTALL_BUTTON); - if (hwndFocus && !ThemeControlEnabled(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON)) - { - hwndFocus = ::GetNextDlgTabItem(m_pTheme->hwndParent, hwndFocus, FALSE); - } - - if (hwndFocus) - { - ::SetFocus(hwndFocus); - } - } - } - } - - ReleaseStr(sczText); - ReleaseStr(sczUnformattedText); - ReleaseStr(sczControlState); - ReleaseStr(sczControlName); - } - - - // - // OnClose - called when the window is trying to be closed. - // - BOOL OnClose() - { - BOOL fClose = FALSE; - - // If we've already succeeded or failed or showing the help page, just close (prompts are annoying if the bootstrapper is done). - if (WIXSTDBA_STATE_APPLIED <= m_state || WIXSTDBA_STATE_HELP == m_state) - { - fClose = TRUE; - } - else // prompt the user or force the cancel if there is no UI. - { - fClose = PromptCancel(m_hWnd, BOOTSTRAPPER_DISPLAY_FULL != m_command.display, m_sczConfirmCloseMessage ? m_sczConfirmCloseMessage : L"Are you sure you want to cancel?", m_pTheme->sczCaption); - } - - // If we're doing progress then we never close, we just cancel to let rollback occur. - if (WIXSTDBA_STATE_APPLYING <= m_state && WIXSTDBA_STATE_APPLIED > m_state) - { - // If we canceled disable cancel button since clicking it again is silly. - if (fClose) - { - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, FALSE); - } - - fClose = FALSE; - } - - return fClose; - } - - - // - // OnClickAcceptCheckbox - allow the install to continue. - // - void OnClickAcceptCheckbox() - { - BOOL fAcceptedLicense = ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX); - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, fAcceptedLicense); - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_NEXT_BUTTON, fAcceptedLicense); - } - - - // - // OnClickOptionsButton - show the options page. - // - void OnClickOptionsButton() - { - SavePageSettings(WIXSTDBA_PAGE_INSTALL); - m_stateInstallPage = m_state; - SetState(WIXSTDBA_STATE_INSTALLDIR, S_OK); - } - - - BOOL CheckNonEmptyField(LPCWSTR wzEditVarID) - { - BOOL bRes = TRUE; - LPWSTR sczFieldValue = NULL; - - if (SUCCEEDED(BalGetStringVariable(wzEditVarID, &sczFieldValue))) - { - if (StrCmpCW(sczFieldValue, L"") == 0) - { - LOC_STRING* pLocString = NULL; - LPWSTR wzLoc = NULL; - LPWSTR sczMessageText = NULL; - - StrAllocFormatted(&wzLoc, L"#(loc.%s)", wzEditVarID); - LocGetString(m_pWixLoc, wzLoc, &pLocString); - StrAllocFormatted(&sczMessageText, L"The field \"%s\" cannot be blank! In order to continue with setup you should fill it.", pLocString->wzText); - - ::MessageBoxW(m_hWnd, sczMessageText, m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OK); - bRes = FALSE; - } - } - return bRes; - } - - - - - BOOL CheckCurrentUserPassword(LPCWSTR wzPasswordVarID) - { - LPWSTR sczUserNameValue = NULL; - LPWSTR sczDomainValue = NULL; - LPWSTR sczPasswordValue = NULL; - - BOOL bRes = SUCCEEDED(BalGetStringVariable(L"ComputerName", &sczDomainValue)) && - SUCCEEDED(BalGetStringVariable(L"LogonUser", &sczUserNameValue)) && - SUCCEEDED(BalGetStringVariable(wzPasswordVarID, &sczPasswordValue)); - - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "CheckCurrentUserPassword. 1"); - - - if (bRes) - { - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "CheckCurrentUserPassword. 2"); - HANDLE hToken; - if (!LogonUserW(sczUserNameValue, sczDomainValue, sczPasswordValue, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &hToken)) - { - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "CheckCurrentUserPassword. 3 - Failed"); - - LPWSTR sczMessageText = NULL; - StrAllocFormatted(&sczMessageText, L"Setup was unable to validate specified password for \"%s\\%s\"! Please double check it.", sczDomainValue, sczUserNameValue); - - ::MessageBoxW(m_hWnd, sczMessageText, m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OK); - bRes = FALSE; - } - else - { - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "CheckCurrentUserPassword. 4 - Succeed"); - } - } - return bRes; - } - - - - - - /* - - BOOL CheckPostgreSQLConnection(LPCWSTR VAR_HOST, LPCWSTR VAR_USER, LPCWSTR VAR_PASS, LPCWSTR DB_ToCheck, BOOL DB_ShouldExists) - { - BOOL bPSQLOk = CheckNonEmptyField(VAR_HOST) && CheckNonEmptyField(VAR_USER) && CheckNonEmptyField(VAR_PASS); - -// if (!bPSQLOk) return FALSE; - - LPWSTR sczPSQLPath = NULL; - LPWSTR sczPSQLDirectory = NULL; - - if (bPSQLOk && SUCCEEDED(PathRelativeToModule(&sczPSQLPath, L"qcPSQL.exe", m_hModule)) && SUCCEEDED(PathGetDirectory(sczPSQLPath, &sczPSQLDirectory))) - { - LPWSTR sczPSQLHost = NULL; - LPWSTR sczPSQLUser = NULL; - LPWSTR sczPSQLPass = NULL; - - if (SUCCEEDED(BalGetStringVariable(VAR_HOST, &sczPSQLHost)) && - SUCCEEDED(BalGetStringVariable(VAR_USER, &sczPSQLUser)) && - SUCCEEDED(BalGetStringVariable(VAR_PASS, &sczPSQLPass)) ) - { - DWORD exitcode = 0; - LPWSTR sczCmdParam = NULL; - if (DB_ToCheck == NULL) - StrAllocFormatted(&sczCmdParam, L"\"%s\" checkconnection -H%s -U%s -P%s", sczPSQLPath, sczPSQLHost, sczPSQLUser, sczPSQLPass); - else - StrAllocFormatted(&sczCmdParam, L"\"%s\" checkdbexists -H%s -U%s -P%s -CKDB%s", sczPSQLPath, sczPSQLHost, sczPSQLUser, sczPSQLPass, DB_ToCheck); - - _STARTUPINFOW si; - _PROCESS_INFORMATION pi; - - ZeroMemory( &si, sizeof(si) ); - si.cb = sizeof(si); - ZeroMemory( &pi, sizeof(pi) ); - - - // Start the child process. - if( CreateProcessW(NULL, // No module name (use command line) - sczCmdParam, // Command line - NULL, // Process handle not inheritable - NULL, // Thread handle not inheritable - FALSE, // Set handle inheritance to FALSE - CREATE_NO_WINDOW, // No creation flags - NULL, // Use parent's environment block - NULL, // Use parent's starting directory - &si, // Pointer to STARTUPINFO structure - &pi ) // Pointer to PROCESS_INFORMATION structure - ) - { - // Wait until child process exits. - WaitForSingleObject( pi.hProcess, INFINITE ); - - // get the process exit code - GetExitCodeProcess(pi.hProcess, (LPDWORD)&exitcode); - - // Close process and thread handles. - CloseHandle( pi.hProcess ); - CloseHandle( pi.hThread ); - } - - - - LPWSTR sczMessageText = NULL; - switch (exitcode) - { - case QCPSQL_ERROR_UNKNOWN: - sczMessageText = L"Setup was unable to connect to the specified database server. Unknown error.\nWould you like to continue anyway?"; - break; - case QCPSQL_ERROR_EXECSQL: - sczMessageText = L"Setup was unable to execute specified command.\nWould you like to continue anyway?"; - break; - case QCPSQL_ERROR_CONNECT: - sczMessageText = L"Setup was unable to connect to the specified database server.\nWould you like to continue anyway?"; - break; - case QCPSQL_ERROR_INVALIDARGS: - sczMessageText = L"Setup was unable to connect to the specified database server. Invalid arguments.\nWould you like to continue anyway?"; - break; - case QCPSQL_SUCCESS_DBNOTEXISTS: - if ((DB_ToCheck != NULL) && (DB_ShouldExists)) - StrAllocFormatted(&sczMessageText, L"The database \"%s\" does not exists on the host \"%s\".\nWould you like to continue anyway?", DB_ToCheck, sczPSQLHost); - break; - case QCPSQL_SUCCESS_DBEXISTS: - if ((DB_ToCheck != NULL) && (!DB_ShouldExists)) - StrAllocFormatted(&sczMessageText, L"The database \"%s\" already exists on the host \"%s\".\nWould you like to continue anyway?", DB_ToCheck, sczPSQLHost); - break; - default: - break; - } - - if (sczMessageText != NULL) - bPSQLOk = (IDYES == ::MessageBoxW(m_hWnd, sczMessageText, m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_YESNO)); - } - } - - return bPSQLOk; - } - */ - - BOOL CheckInstallPathIsValid(LPCWSTR wzInstallPath) - { - BOOL bPathIsValid = TRUE; - - if (StrCmpCW(wzInstallPath, L"") == 0) - { - bPathIsValid = FALSE; - ::MessageBoxW(m_hWnd, L"The install location cannot be blank. You must enter a full path with drive letter, like:\n\tC:\\Program Files\\App\n\nor a UNC path, like\n\t\\\\ServerName\\AppShare", m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OK); - } else { - DWORD i = 0; - LPCWSTR wz = wzInstallPath; - BOOL bInvalidCharFound = FALSE; - while (*wz) - { - ++i; - if ((L'/' == *wz) || ((L':' == *wz) && (i != 2)) || (L'*' == *wz) || (L'?' == *wz) || - (L'"' == *wz) || (L'<' == *wz) || (L'>' == *wz) || (L'|' == *wz)) - bInvalidCharFound = TRUE; - ++wz; - } - - if (bInvalidCharFound) - { - bPathIsValid = FALSE; - ::MessageBoxW(m_hWnd, L"The install location cannot include any of the following characters:\n\n/ : * ? \" < > |", m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OK); - } - } - return bPathIsValid; - } - - - BOOL CheckEmailAddressIsValid(LPCWSTR wzEmailVarID, LPCWSTR wzPassVarID = NULL, BOOL AllowBlank = TRUE) - { - BOOL bRes = TRUE; - LPWSTR sczEmailValue = NULL; - LPWSTR sczPassValue = NULL; - - if (SUCCEEDED(BalGetStringVariable(wzEmailVarID, &sczEmailValue))) - { - LOC_STRING* pLocString = NULL; - LPWSTR wzLoc = NULL; - LPWSTR sczMessageText = NULL; - - StrAllocFormatted(&wzLoc, L"#(loc.%s)", wzEmailVarID); - LocGetString(m_pWixLoc, wzLoc, &pLocString); - - BOOL bIsBlank = (StrCmpCW(sczEmailValue, L"") == 0); - - if (bIsBlank && AllowBlank) - return TRUE; - - if (bIsBlank) - { - bRes = FALSE; - StrAllocFormatted(&sczMessageText, L"The field \"%s\" cannot be blank! In order to continue with setup you should fill it.", pLocString->wzText); - } else { - DWORD i = 0; - DWORD iAt = 0; - DWORD iPt = 0; - - LPCWSTR wz = sczEmailValue; - while (*wz) - { - ++i; - if (L'@' == *wz) iAt = i; - if (L'.' == *wz) iPt = i; - ++wz; - } - bRes = (1 < iAt) && (iAt < iPt); - - if (!bRes) - StrAllocFormatted(&sczMessageText, L"The field \"%s\" dosen't seems to be a valid email address! Please double check that.", pLocString->wzText); - } - - if (!bRes) - ::MessageBoxW(m_hWnd, sczMessageText, m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OK); - else { - if (wzPassVarID != NULL) - { - if (SUCCEEDED(BalGetStringVariable(wzPassVarID, &sczPassValue))) - if (StrCmpCW(sczEmailValue, L"") == 0) { - bRes = FALSE; - ::MessageBoxW(m_hWnd, L"You specified a valid email address but the account password is blank. The password is required!", m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OK); - } - } - } - - } - - return bRes; - } - - - void OnClickNextButton() - { - BOOL bOkToContinue = TRUE; - LPWSTR sczPath = NULL; - - switch (m_state) - { - case WIXSTDBA_STATE_INSTALLDIR: - ThemeGetTextControl(m_pTheme, WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX, &sczPath); - bOkToContinue = CheckInstallPathIsValid(sczPath); - - if (bOkToContinue) { - m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_INSTALL_FOLDER, sczPath); - SavePageSettings(WIXSTDBA_PAGE_INSTALLDIR); - SetState(WIXSTDBA_STATE_SVC_OPTIONS, S_OK); - - // Display the elevation shield if perMachine installation - LONGLONG llElevated = 0; - if (SUCCEEDED(BalGetNumericVariable(WIXSTDBA_VARIABLE_PERMACHINE_INSTALL, &llElevated))) - ThemeControlElevates(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, (llElevated == 1)); - } - break; - - default: - SavePageSettings(WIXSTDBA_PAGE_INSTALL); - m_stateInstallPage = m_state; - SetState(WIXSTDBA_STATE_INSTALLDIR, S_OK); - break; - } - } - - - // - // OnClickInstallScope - allow user to choose between a perMachine and perUser install - // - void OnClickInstallScope() - { - LPWSTR sczPath = NULL; - LPWSTR sczFPath = NULL; - BOOL fPerMachineInst = ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_PERMACHINE_RADIO); - - - if (fPerMachineInst) - { - if (SUCCEEDED(BalGetStringVariable(WIXSTDBA_VARIABLE_PERMACHINE_INSTALL_FOLDER, &sczPath)) - && SUCCEEDED(BalFormatString(sczPath, &sczFPath))) - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX, sczFPath); - } - else - { - if (SUCCEEDED(BalGetStringVariable(WIXSTDBA_VARIABLE_PERUSER_INSTALL_FOLDER, &sczPath)) - && SUCCEEDED(BalFormatString(sczPath, &sczFPath))) - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX, sczFPath); - } - } - - // - // OnClickInstallPostgressCheckbox - we will set defaults value and disable controls if checkbox was checked. - // - void OnClickSkipRegistrationCheckbox() - { - BOOL fSkipReg = ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_SKIPREG_CHECKBOX); - BOOL fSignIn = ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_REGSIGNIN_RADIO); - - //if (fSkipReg) - //{ - // ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_DBHOST_EDIT, L"localhost"); - // ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_DBUSER_EDIT, L"postgres"); - // ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_DBPASS_EDIT, L"postgres"); - //} - - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_REGMAIL_LABEL, !fSkipReg && !fSignIn); - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_REGUSER_LABEL, !fSkipReg); - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_REGPASS_LABEL, !fSkipReg); - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_REGMAIL_EDIT, !fSkipReg && !fSignIn); - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_REGUSER_EDIT, !fSkipReg); - ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_REGPASS_EDIT, !fSkipReg); - } - - - - // - // OnClickInstallButton - start the install by planning the packages. - // - void OnClickInstallButton() - { - m_fOverallInstallationStarted = TRUE; - BOOL bOkToContinue = TRUE; - BOOL fSignIn = ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_REGSIGNIN_RADIO); - BOOL fSkipReg = ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_SKIPREG_CHECKBOX); - - SavePageSettings(WIXSTDBA_PAGE_SVC_OPTIONS); - - if (!fSkipReg) - { - bOkToContinue = CheckNonEmptyField(WIXSTDBA_VARIABLE_REG_USER) && CheckNonEmptyField(WIXSTDBA_VARIABLE_REG_PASS); - if (bOkToContinue) - { - if (fSignIn) - { - LPWSTR wzUserName = NULL; - LPWSTR wzUserPass = NULL; - if (SUCCEEDED(BalGetStringVariable(WIXSTDBA_VARIABLE_REG_USER, &wzUserName)) && - SUCCEEDED(BalGetStringVariable(WIXSTDBA_VARIABLE_REG_PASS, &wzUserPass))) - { - bOkToContinue = REST_ValidateUserLogin(wzUserName, wzUserPass); - } - } - else - { - bOkToContinue = CheckNonEmptyField(WIXSTDBA_VARIABLE_REG_MAIL) && CheckEmailAddressIsValid(WIXSTDBA_VARIABLE_REG_MAIL); - MessageBoxW(m_hWnd, L"Creating a meteor developer account from here it wasn't implemnted yet.", m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OK); - } - } - } - - SavePageSettings(WIXSTDBA_PAGE_INSTALL); - - if (bOkToContinue) this->OnPlan(BOOTSTRAPPER_ACTION_INSTALL); - } - - - void OnClickBackButton() - { - BOOL bOkToContinue = TRUE; - LPWSTR sczPath = NULL; - - switch (m_state) - { - case WIXSTDBA_STATE_INSTALLDIR: - ThemeGetTextControl(m_pTheme, WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX, &sczPath); - bOkToContinue = CheckInstallPathIsValid(sczPath); - - if (bOkToContinue) { - m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_INSTALL_FOLDER, sczPath); - SavePageSettings(WIXSTDBA_PAGE_INSTALLDIR); - SetState(m_stateInstallPage, S_OK); - } - - break; - - case WIXSTDBA_STATE_SVC_OPTIONS: - SavePageSettings(WIXSTDBA_PAGE_SVC_OPTIONS); - SetState(WIXSTDBA_STATE_INSTALLDIR, S_OK); - break; - } - - } - - - // - // OnClickOptionsBrowseButton - browse for install folder on the options page. - // - void OnClickOptionsBrowseButton(DWORD dwControl) - { - WCHAR wzPath[MAX_PATH] = { }; - BROWSEINFOW browseInfo = { }; - PIDLIST_ABSOLUTE pidl = NULL; - PIDLIST_ABSOLUTE pidlRoot = NULL; - - ::SHGetFolderLocation(m_hWnd, CSIDL_DRIVES, NULL, 0, &pidlRoot); - - browseInfo.hwndOwner = m_hWnd; - browseInfo.pszDisplayName = wzPath; - browseInfo.lpszTitle = m_pTheme->sczCaption; - browseInfo.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI; - browseInfo.pidlRoot = pidlRoot; - pidl = ::SHBrowseForFolderW(&browseInfo); - if (pidl && ::SHGetPathFromIDListW(pidl, wzPath)) - { - switch (dwControl) - { - case WIXSTDBA_CONTROL_BROWSE_BUTTON: - ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX, wzPath); - break; - } - } - - if (pidl) - { - ::CoTaskMemFree(pidl); - } - - return; - } - - // - // OnClickOptionsOkButton - accept the changes made by the options page. - // - void OnClickOptionsOkButton() - { - HRESULT hr = S_OK; - LPWSTR sczPath = NULL; - - if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX)) - { - hr = ThemeGetTextControl(m_pTheme, WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX, &sczPath); - ExitOnFailure(hr, "Failed to get text from folder edit box."); - - // TODO: verify the path is valid. - - hr = m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_INSTALL_FOLDER, sczPath); - ExitOnFailure(hr, "Failed to set the install folder."); - } - - - SavePageSettings(WIXSTDBA_PAGE_INSTALLDIR); - -LExit: - SetState(m_stateInstallPage, S_OK); - return; - } - - - // - // OnClickOptionsCancelButton - discard the changes made by the options page. - // - void OnClickOptionsCancelButton() - { - SetState(m_stateInstallPage, S_OK); - } - - - // - // OnClickRepairButton - start the repair. - // - void OnClickRepairButton() - { - this->OnPlan(BOOTSTRAPPER_ACTION_REPAIR); - } - - - // - // OnClickUninstallButton - start the uninstall. - // - void OnClickUninstallButton() - { - this->OnPlan(BOOTSTRAPPER_ACTION_UNINSTALL); - } - - - - void TryLaunchAfterInstall(LPWSTR wzVarTargetPath) - { - BOOL fLaunchAfterInstallTargetExists = BalStringVariableExists(wzVarTargetPath); - - HRESULT hr = S_OK; - LPWSTR sczUnformattedLaunchTarget = NULL; - LPWSTR sczLaunchTarget = NULL; - LPWSTR sczUnformattedArguments = NULL; - LPWSTR sczArguments = NULL; - LPWSTR sczRunOnceValue = NULL; - - int nCmdShow = SW_SHOWNORMAL; - - if (fLaunchAfterInstallTargetExists) - { - hr = BalGetStringVariable(wzVarTargetPath, &sczUnformattedLaunchTarget); - hr = BalFormatString(sczUnformattedLaunchTarget, &sczLaunchTarget); - } - - if (m_fInstallSucceed && fLaunchAfterInstallTargetExists) - { - - if (!m_fRestartRequired) - { - DWORD dwAttr; - if (FileExistsEx(sczLaunchTarget, &dwAttr)) - ShelExec(sczLaunchTarget, sczArguments, L"open", NULL, nCmdShow, m_hWnd, NULL); - } - } - - ReleaseStr(sczUnformattedLaunchTarget); - ReleaseStr(sczLaunchTarget); - ReleaseStr(sczUnformattedArguments); - ReleaseStr(sczArguments); - ReleaseStr(sczRunOnceValue); - - return; - } - - // - // OnClickCloseButton - close the application. - // - void OnClickCloseButton() - { - TryLaunchAfterInstall(L"Launch_IISStartServerPath"); - TryLaunchAfterInstall(L"Launch_EverywarePOSPath"); - ::SendMessageW(m_hWnd, WM_CLOSE, 0, 0); - return; - } - - - // - // OnClickEulaLink - show the end user license agreement. - // - void OnClickEulaLink() - { - HRESULT hr = S_OK; - LPWSTR sczLicenseUrl = NULL; - LPWSTR sczLicensePath = NULL; - LPWSTR sczLicenseDirectory = NULL; - URI_PROTOCOL protocol = URI_PROTOCOL_UNKNOWN; - - hr = StrAllocString(&sczLicenseUrl, m_sczLicenseUrl, 0); - BalExitOnFailure1(hr, "Failed to copy license URL: %ls", m_sczLicenseUrl); - - hr = LocLocalizeString(m_pWixLoc, &sczLicenseUrl); - BalExitOnFailure1(hr, "Failed to localize license URL: %ls", m_sczLicenseUrl); - - hr = BalFormatString(sczLicenseUrl, &sczLicenseUrl); - BalExitOnFailure1(hr, "Failed to get formatted license URL: %ls", m_sczLicenseUrl); - - hr = UriProtocol(sczLicenseUrl, &protocol); - if (FAILED(hr) || URI_PROTOCOL_UNKNOWN == protocol) - { - // Probe for localised license file - hr = PathRelativeToModule(&sczLicensePath, sczLicenseUrl, m_hModule); - if (SUCCEEDED(hr)) - { - hr = PathGetDirectory(sczLicensePath, &sczLicenseDirectory); - if (SUCCEEDED(hr)) - { - hr = LocProbeForFile(sczLicenseDirectory, PathFile(sczLicenseUrl), m_sczLanguage, &sczLicensePath); - } - } - } - - hr = ShelExec(sczLicensePath ? sczLicensePath : sczLicenseUrl, NULL, L"open", NULL, SW_SHOWDEFAULT, m_hWnd, NULL); - BalExitOnFailure(hr, "Failed to launch URL to EULA."); - -LExit: - ReleaseStr(sczLicensePath); - ReleaseStr(sczLicenseUrl); - ReleaseStr(sczLicenseDirectory); - - return; - } - - - // - // OnClickUpgradeLink - download the upgrade. - // - void OnClickUpgradeLink() - { - this->OnPlan(BOOTSTRAPPER_ACTION_UPDATE_REPLACE); - - m_fUpdating = TRUE; - - return; - } - - - // - // OnClickLaunchButton - launch the app from the success page. - // - void OnClickLaunchButton() - { - HRESULT hr = S_OK; - LPWSTR sczUnformattedLaunchTarget = NULL; - LPWSTR sczLaunchTarget = NULL; - LPWSTR sczUnformattedArguments = NULL; - LPWSTR sczArguments = NULL; - int nCmdShow = SW_SHOWNORMAL; - - hr = BalGetStringVariable(WIXSTDBA_VARIABLE_LAUNCH_TARGET_PATH, &sczUnformattedLaunchTarget); - BalExitOnFailure1(hr, "Failed to get launch target variable '%ls'.", WIXSTDBA_VARIABLE_LAUNCH_TARGET_PATH); - - hr = BalFormatString(sczUnformattedLaunchTarget, &sczLaunchTarget); - BalExitOnFailure1(hr, "Failed to format launch target variable: %ls", sczUnformattedLaunchTarget); - - if (BalStringVariableExists(WIXSTDBA_VARIABLE_LAUNCH_ARGUMENTS)) - { - hr = BalGetStringVariable(WIXSTDBA_VARIABLE_LAUNCH_ARGUMENTS, &sczUnformattedArguments); - BalExitOnFailure1(hr, "Failed to get launch arguments '%ls'.", WIXSTDBA_VARIABLE_LAUNCH_ARGUMENTS); - - hr = BalFormatString(sczUnformattedArguments, &sczArguments); - BalExitOnFailure1(hr, "Failed to format launch arguments variable: %ls", sczUnformattedArguments); - } - - if (BalStringVariableExists(WIXSTDBA_VARIABLE_LAUNCH_HIDDEN)) - { - nCmdShow = SW_HIDE; - } - - hr = ShelExec(sczLaunchTarget, sczArguments, L"open", NULL, nCmdShow, m_hWnd, NULL); - BalExitOnFailure1(hr, "Failed to launch target: %ls", sczLaunchTarget); - - ::PostMessageW(m_hWnd, WM_CLOSE, 0, 0); - -LExit: - ReleaseStr(sczLaunchTarget); - ReleaseStr(sczUnformattedLaunchTarget); - ReleaseStr(sczArguments); - ReleaseStr(sczUnformattedArguments); - - return; - } - - - // - // OnClickRestartButton - allows the restart and closes the app. - // - void OnClickRestartButton() - { - AssertSz(m_fRestartRequired, "Restart must be requested to be able to click on the restart button."); - - m_fAllowRestart = TRUE; - ::SendMessageW(m_hWnd, WM_CLOSE, 0, 0); - - return; - } - - - // - // OnClickLogFileLink - show the log file. - // - void OnClickLogFileLink() - { - HRESULT hr = S_OK; - LPWSTR sczLogFile = NULL; - - hr = BalGetStringVariable(m_Bundle.sczLogVariable, &sczLogFile); - BalExitOnFailure1(hr, "Failed to get log file variable '%ls'.", m_Bundle.sczLogVariable); - - hr = ShelExec(L"notepad.exe", sczLogFile, L"open", NULL, SW_SHOWDEFAULT, m_hWnd, NULL); - BalExitOnFailure1(hr, "Failed to open log file target: %ls", sczLogFile); - -LExit: - ReleaseStr(sczLogFile); - - return; - } - - - // - // SetState - // - void SetState( - __in WIXSTDBA_STATE state, - __in HRESULT hrStatus - ) - { - if (FAILED(hrStatus)) - { - m_hrFinal = hrStatus; - } - - if (FAILED(m_hrFinal)) - { - state = WIXSTDBA_STATE_FAILED; - } - - if (WIXSTDBA_STATE_INSTALLDIR == state || m_state < state) - { - ::PostMessageW(m_hWnd, WM_WIXSTDBA_CHANGE_STATE, 0, state); - } - - if (WIXSTDBA_STATE_INSTALLDIR == state || m_state < state) - { - ::PostMessageW(m_hWnd, WM_WIXSTDBA_CHANGE_STATE, 0, state); - } - - if (WIXSTDBA_STATE_SVC_OPTIONS == state || m_state < state) - { - ::PostMessageW(m_hWnd, WM_WIXSTDBA_CHANGE_STATE, 0, state); - } - } - - - void DeterminePageId( - __in WIXSTDBA_STATE state, - __out DWORD* pdwPageId - ) - { - if (BOOTSTRAPPER_DISPLAY_PASSIVE == m_command.display) - { - switch (state) - { - case WIXSTDBA_STATE_INITIALIZED: - *pdwPageId = BOOTSTRAPPER_ACTION_HELP == m_command.action ? m_rgdwPageIds[WIXSTDBA_PAGE_HELP] : m_rgdwPageIds[WIXSTDBA_PAGE_LOADING]; - break; - - case WIXSTDBA_STATE_HELP: - *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_HELP]; - break; - - case WIXSTDBA_STATE_DETECTING: - *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_LOADING] ? m_rgdwPageIds[WIXSTDBA_PAGE_LOADING] : m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS_PASSIVE] ? m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS_PASSIVE] : m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS]; - break; - - case WIXSTDBA_STATE_DETECTED: __fallthrough; - case WIXSTDBA_STATE_PLANNING: __fallthrough; - case WIXSTDBA_STATE_PLANNED: __fallthrough; - case WIXSTDBA_STATE_APPLYING: __fallthrough; - case WIXSTDBA_STATE_CACHING: __fallthrough; - case WIXSTDBA_STATE_CACHED: __fallthrough; - case WIXSTDBA_STATE_EXECUTING: __fallthrough; - case WIXSTDBA_STATE_EXECUTED: - *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS_PASSIVE] ? m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS_PASSIVE] : m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS]; - break; - - default: - *pdwPageId = 0; - break; - } - } - else if (BOOTSTRAPPER_DISPLAY_FULL == m_command.display) - { - switch (state) - { - case WIXSTDBA_STATE_INITIALIZING: - *pdwPageId = 0; - break; - - case WIXSTDBA_STATE_INITIALIZED: - *pdwPageId = BOOTSTRAPPER_ACTION_HELP == m_command.action ? m_rgdwPageIds[WIXSTDBA_PAGE_HELP] : m_rgdwPageIds[WIXSTDBA_PAGE_LOADING]; - break; - - case WIXSTDBA_STATE_HELP: - *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_HELP]; - break; - - case WIXSTDBA_STATE_DETECTING: - *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_LOADING]; - break; - - case WIXSTDBA_STATE_DETECTED: - switch (m_command.action) - { - case BOOTSTRAPPER_ACTION_INSTALL: - *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_INSTALL]; - break; - - case BOOTSTRAPPER_ACTION_MODIFY: __fallthrough; - case BOOTSTRAPPER_ACTION_REPAIR: __fallthrough; - case BOOTSTRAPPER_ACTION_UNINSTALL: - *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_MODIFY]; - break; - } - break; - - case WIXSTDBA_STATE_INSTALLDIR: - *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_INSTALLDIR]; - break; - - case WIXSTDBA_STATE_SVC_OPTIONS: - *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_SVC_OPTIONS]; - break; - - case WIXSTDBA_STATE_PLANNING: __fallthrough; - case WIXSTDBA_STATE_PLANNED: __fallthrough; - case WIXSTDBA_STATE_APPLYING: __fallthrough; - case WIXSTDBA_STATE_CACHING: __fallthrough; - case WIXSTDBA_STATE_CACHED: __fallthrough; - case WIXSTDBA_STATE_EXECUTING: __fallthrough; - case WIXSTDBA_STATE_EXECUTED: - *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS]; - break; - - case WIXSTDBA_STATE_APPLIED: - *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_SUCCESS]; - CopyBundleLogToSpecifiedPath(); - break; - - case WIXSTDBA_STATE_FAILED: - *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_FAILURE]; - CopyBundleLogToSpecifiedPath(); - break; - } - } - } - - - HRESULT EvaluateConditions() - { - HRESULT hr = S_OK; - BOOL fResult = FALSE; - - for (DWORD i = 0; i < m_Conditions.cConditions; ++i) - { - BAL_CONDITION* pCondition = m_Conditions.rgConditions + i; - - hr = BalConditionEvaluate(pCondition, m_pEngine, &fResult, &m_sczFailedMessage); - BalExitOnFailure(hr, "Failed to evaluate condition."); - - if (!fResult) - { - hr = E_WIXSTDBA_CONDITION_FAILED; - BalExitOnFailure1(hr, "Bundle condition evaluated to false: %ls", pCondition->sczCondition); - } - } - - ReleaseNullStr(m_sczFailedMessage); - -LExit: - return hr; - } - - - - void CopyBundleLogToSpecifiedPath() - { - /// On package install complete, if WIXSTDBA_VARIABLE_LOGSPATH is defined - /// then will move bundle installation log to the specified path. - if (!m_fOverallInstallationStarted) - return; - - if (BalStringVariableExists(WIXSTDBA_VARIABLE_LOGSPATH)) - { - LPWSTR wzBundleLog = NULL; - LPWSTR wzInstallLogPath = NULL; - LPWSTR wzDstBundleLog = NULL; - - if ( SUCCEEDED(BalGetStringVariable(WIXSTDBA_VARIABLE_LOGSPATH, &wzInstallLogPath)) && - SUCCEEDED(BalGetStringVariable(L"WixBundleLog", &wzBundleLog))) - { - StrAllocFormatted(&wzDstBundleLog, L"%s\\%s", wzInstallLogPath, PathFile(wzBundleLog)); - DirEnsureExists(wzInstallLogPath, NULL); - FileEnsureCopy(wzBundleLog, wzDstBundleLog, TRUE); - } else - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Setup was unable to copy bundle log to the specified installation log path."); - } - - return; - } - - - - void SetTaskbarButtonProgress( - __in DWORD dwOverallPercentage - ) - { - HRESULT hr = S_OK; - - if (m_fTaskbarButtonOK) - { - hr = m_pTaskbarList->SetProgressValue(m_hWnd, dwOverallPercentage, 100UL); - BalExitOnFailure1(hr, "Failed to set taskbar button progress to: %d%%.", dwOverallPercentage); - } - -LExit: - return; - } - - - void SetTaskbarButtonState( - __in TBPFLAG tbpFlags - ) - { - HRESULT hr = S_OK; - - if (m_fTaskbarButtonOK) - { - hr = m_pTaskbarList->SetProgressState(m_hWnd, tbpFlags); - BalExitOnFailure1(hr, "Failed to set taskbar button state.", tbpFlags); - } - -LExit: - return; - } - - - void SetProgressState( - __in HRESULT hrStatus - ) - { - TBPFLAG flag = TBPF_NORMAL; - - if (IsCanceled() || HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) == hrStatus) - { - flag = TBPF_PAUSED; - } - else if (IsRollingBack() || FAILED(hrStatus)) - { - flag = TBPF_ERROR; - } - - SetTaskbarButtonState(flag); - } - - - void SavePageSettings( - __in WIXSTDBA_PAGE page - ) - { - THEME_PAGE* pPage = NULL; - - pPage = ThemeGetPage(m_pTheme, m_rgdwPageIds[page]); - if (pPage) - { - for (DWORD i = 0; i < pPage->cControlIndices; ++i) - { - // Loop through all the checkbox controls (or buttons with BS_AUTORADIOBUTTON) with names and set a Burn variable with that name to true or false. - THEME_CONTROL* pControl = m_pTheme->rgControls + pPage->rgdwControlIndices[i]; - if ((THEME_CONTROL_TYPE_CHECKBOX == pControl->type) || - (THEME_CONTROL_TYPE_BUTTON == pControl->type && (BS_AUTORADIOBUTTON == (BS_AUTORADIOBUTTON & pControl->dwStyle)) && - pControl->sczName && *pControl->sczName)) - { - BOOL bChecked = ThemeIsControlChecked(m_pTheme, pControl->wId); - m_pEngine->SetVariableNumeric(pControl->sczName, bChecked ? 1 : 0); - } - - // Loop through all the editbox controls with names and set a Burn variable with that name to the contents. - if (THEME_CONTROL_TYPE_EDITBOX == pControl->type && pControl->sczName && *pControl->sczName && - (WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX != pControl->wId)) - { - LPWSTR sczValue = NULL; - ThemeGetTextControl(m_pTheme, pControl->wId, &sczValue); - m_pEngine->SetVariableString(pControl->sczName, sczValue); - } - } - } - } - - - - HRESULT LoadBootstrapperBAFunctions() - { - HRESULT hr = S_OK; - LPWSTR sczBafPath = NULL; - - hr = PathRelativeToModule(&sczBafPath, L"bafunctions.dll", m_hModule); - BalExitOnFailure(hr, "Failed to get path to BA function DLL."); - -#ifdef DEBUG - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXEXTBA: LoadBootstrapperBAFunctions() - BA function DLL '%ls'", sczBafPath); -#endif - - m_hBAFModule = ::LoadLibraryW(sczBafPath); - if (m_hBAFModule) - { - PFN_BOOTSTRAPPER_BA_FUNCTION_CREATE pfnBAFunctionCreate = reinterpret_cast(::GetProcAddress(m_hBAFModule, "CreateBootstrapperBAFunction")); - BalExitOnNullWithLastError1(pfnBAFunctionCreate, hr, "Failed to get CreateBootstrapperBAFunction entry-point from: %ls", sczBafPath); - - hr = pfnBAFunctionCreate(m_pEngine, m_hBAFModule, &m_pBAFunction); - BalExitOnFailure(hr, "Failed to create BA function."); - } -#ifdef DEBUG - else - { - BalLogError(HRESULT_FROM_WIN32(::GetLastError()), "WIXEXTBA: LoadBootstrapperBAFunctions() - Failed to load DLL %ls", sczBafPath); - } -#endif - -LExit: - if (m_hBAFModule && !m_pBAFunction) - { - ::FreeLibrary(m_hBAFModule); - m_hBAFModule = NULL; - } - ReleaseStr(sczBafPath); - - return hr; - } - - - #pragma comment( lib,"Wininet.lib") - - -#define BUF_LEN 1024 - -BOOL POSTRequest( - __in LPCSTR szHost, - __in LPCSTR szApiPath, - __in LPSTR szFormData, - __out LPSTR *ppszResponseMessage) -{ - BOOL bRes = false; - StrAnsiAlloc(ppszResponseMessage, BUF_LEN); - - LPCSTR header = "Content-Type: application/x-www-form-urlencoded"; - LPCSTR method = "POST"; - LPCSTR agent = "Mozilla/4.0 (compatible; MSIE 1.0)"; - - HINTERNET internet = InternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); - if(internet != NULL) - { - HINTERNET connect = InternetConnectA(internet, szHost, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0); - if(connect != NULL) - { - HINTERNET request = HttpOpenRequestA(connect, method, szApiPath, "HTTP/1.1", NULL, NULL, - INTERNET_FLAG_HYPERLINK | INTERNET_FLAG_IGNORE_CERT_CN_INVALID | - INTERNET_FLAG_IGNORE_CERT_DATE_INVALID | - INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP | - INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS | - INTERNET_FLAG_NO_AUTH | - INTERNET_FLAG_NO_CACHE_WRITE | - INTERNET_FLAG_NO_UI | - INTERNET_FLAG_PRAGMA_NOCACHE | - INTERNET_FLAG_RELOAD, NULL); - - if(request != NULL) - { - int datalen = 0; - if(szFormData != NULL) datalen = strlen(szFormData); - int headerlen = 0; - if(header != NULL) headerlen = strlen(header); - - if(HttpSendRequestA(request, header, headerlen, szFormData, datalen)) - { - // We have succesfully sent the POST request - bRes = true; - - // Now we should read the response - DWORD bytesRead; - char holdBuff[4096]; - char* temp = holdBuff; - while (InternetReadFile(request, temp, 1024, &bytesRead) == TRUE && bytesRead > 0) - { - temp += bytesRead; - } - *temp = '\0'; // manually append NULL terminator - - StringCchPrintfA(*ppszResponseMessage, BUF_LEN, holdBuff); - } - else - StringCchPrintfA(*ppszResponseMessage, BUF_LEN, "Failed to send http request."); - - InternetCloseHandle(request); - } - else - StringCchPrintfA(*ppszResponseMessage, BUF_LEN, "Failed to open http request."); - } - else - StringCchPrintfA(*ppszResponseMessage, BUF_LEN, "Connectiong to %s failed.", szHost); - - InternetCloseHandle(connect); - } - else - StringCchPrintfA(*ppszResponseMessage, BUF_LEN, "Initialize internet resources failed."); - InternetCloseHandle(internet); - - return bRes; -} - - -BOOL REST_ValidateUserLogin( - __in LPCWSTR wzUserName, - __in LPCWSTR wzPassword/*, - __out LPWSTR *ppwzErrorMessage*/ - ) -{ - BOOL bRes = false; - wchar_t wzFormData[BUF_LEN] = L""; - StringCchPrintfW(wzFormData, BUF_LEN, L"username=%s&password=%s", wzUserName, wzPassword); - - size_t i; - char *pMBFormData = (char *)malloc( BUF_LEN ); - wcstombs_s(&i, pMBFormData, (size_t)BUF_LEN, wzFormData, (size_t)BUF_LEN ); - - char *pMBDataResponse = NULL; - wchar_t wzErrorMessage[BUF_LEN] = L""; - - if (POSTRequest("accounts-stub.meteor.com", "/api/v1/login", pMBFormData, &pMBDataResponse)) - { - JSONValue *JSONResponse = JSON::Parse(pMBDataResponse); - if (JSONResponse != NULL) - { - size_t n; - - // Retrieve the main object - JSONObject JSONRoot; - if (JSONResponse->IsObject() == false) - { - mbstowcs_s(&n, wzErrorMessage, BUF_LEN, pMBDataResponse, BUF_LEN); - } - else - { - JSONRoot = JSONResponse->AsObject(); - if (JSONRoot.find(L"error") != JSONRoot.end() && JSONRoot[L"error"]->IsString()) - { - StringCchPrintfW(wzErrorMessage, BUF_LEN, JSONRoot[L"error"]->AsString().c_str()); - } - else - { - bRes = true; - - LPWSTR wzUMSFilePath = NULL; - LPWSTR wzUMSFileExpPath = NULL; - if (SUCCEEDED(BalGetStringVariable(WIXSTDBA_VARIABLE_USERMETEORSESSIONFILE, &wzUMSFilePath))) - { - if (SUCCEEDED(PathExpand(&wzUMSFileExpPath, wzUMSFilePath, PATH_EXPAND_ENVIRONMENT | PATH_EXPAND_FULLPATH))) - { - FileEnsureDelete(wzUMSFileExpPath); - HANDLE hFile = CreateFileW(wzUMSFileExpPath, GENERIC_ALL, 0, 0L, 1, 0x80L, 0); - if (hFile != INVALID_HANDLE_VALUE) - { - DWORD bytesWritten; - WriteFile(hFile, pMBDataResponse, strlen(pMBDataResponse), &bytesWritten, NULL); - CloseHandle( hFile); - } - } - } - } - } - } - else - wcsncat_s(wzErrorMessage, L"Unknown error.", BUF_LEN-1); - - // Clean up JSON object - delete JSONResponse; - } - - - if (bRes == false) - { - wchar_t wzMessage[BUF_LEN] = L""; - StringCchPrintfW(wzMessage, BUF_LEN, L"Setup was unable to check your account. %s", wzErrorMessage); - MessageBoxW(m_hWnd, wzMessage, m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OK); - } - - return bRes; -} - - - HRESULT DAPI LocGetString( - __in const WIX_LOCALIZATION* pWixLoc, - __in_z LPCWSTR wzId, - __out LOC_STRING** ppLocString - ) - { - HRESULT hr = E_NOTFOUND; - LOC_STRING* pLocString = NULL; - - for (DWORD i = 0; i < pWixLoc->cLocStrings; ++i) - { - pLocString = pWixLoc->rgLocStrings + i; - - if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pLocString->wzId, -1, wzId, -1)) - { - *ppLocString = pLocString; - hr = S_OK; - break; - } - } - - return hr; - } -public: - // - // Constructor - intitialize member variables. - // - CWixStandardBootstrapperApplication( - __in HMODULE hModule, - __in BOOL fPrereq, - __in IBootstrapperEngine* pEngine, - __in const BOOTSTRAPPER_COMMAND* pCommand - ) : CBalBaseBootstrapperApplication(pEngine, pCommand, 3, 3000) - { - m_hModule = hModule; - memcpy_s(&m_command, sizeof(m_command), pCommand, sizeof(BOOTSTRAPPER_COMMAND)); - - // Pre-req BA should only show help or do an install (to launch the Managed BA which can then do the right action). - if (fPrereq && BOOTSTRAPPER_ACTION_HELP != m_command.action && BOOTSTRAPPER_ACTION_INSTALL != m_command.action) - { - m_command.action = BOOTSTRAPPER_ACTION_INSTALL; - } - else // maybe modify the action state if the bundle is or is not already installed. - { - LONGLONG llInstalled = 0; - HRESULT hr = BalGetNumericVariable(L"WixBundleInstalled", &llInstalled); - if (SUCCEEDED(hr) && BOOTSTRAPPER_RESUME_TYPE_REBOOT != m_command.resumeType && 0 < llInstalled && BOOTSTRAPPER_ACTION_INSTALL == m_command.action) - { - m_command.action = BOOTSTRAPPER_ACTION_MODIFY; - } - else if (0 == llInstalled && (BOOTSTRAPPER_ACTION_MODIFY == m_command.action || BOOTSTRAPPER_ACTION_REPAIR == m_command.action)) - { - m_command.action = BOOTSTRAPPER_ACTION_INSTALL; - } - } - - m_plannedAction = BOOTSTRAPPER_ACTION_UNKNOWN; - - // When resuming from restart doing some install-like operation, try to find the package that forced the - // restart. We'll use this information during planning. - m_sczAfterForcedRestartPackage = NULL; - - if (BOOTSTRAPPER_RESUME_TYPE_REBOOT == m_command.resumeType && BOOTSTRAPPER_ACTION_UNINSTALL < m_command.action) - { - // Ensure the forced restart package variable is null when it is an empty string. - HRESULT hr = BalGetStringVariable(L"WixBundleForcedRestartPackage", &m_sczAfterForcedRestartPackage); - if (FAILED(hr) || !m_sczAfterForcedRestartPackage || !*m_sczAfterForcedRestartPackage) - { - ReleaseNullStr(m_sczAfterForcedRestartPackage); - } - } - - m_pWixLoc = NULL; - memset(&m_Bundle, 0, sizeof(m_Bundle)); - memset(&m_Conditions, 0, sizeof(m_Conditions)); - m_sczConfirmCloseMessage = NULL; - m_sczFailedMessage = NULL; - - m_sczLanguage = NULL; - m_pTheme = NULL; - memset(m_rgdwPageIds, 0, sizeof(m_rgdwPageIds)); - m_dwCurrentPage = 0; - m_hUiThread = NULL; - m_fRegistered = FALSE; - m_hWnd = NULL; - - m_state = WIXSTDBA_STATE_INITIALIZING; - m_hrFinal = S_OK; - - m_fDowngrading = FALSE; - m_restartResult = BOOTSTRAPPER_APPLY_RESTART_NONE; - m_fRestartRequired = FALSE; - m_fAllowRestart = FALSE; - - m_sczLicenseFile = NULL; - m_sczLicenseUrl = NULL; - m_fSuppressOptionsUI = FALSE; - m_fSuppressDowngradeFailure = FALSE; - m_fSuppressRepair = FALSE; - m_fShowVersion = FALSE; - m_fIsRepair = FALSE; - m_fIsUninstall = FALSE; - m_fInstallSucceed = FALSE; - m_fIsProductCore = FALSE; - m_sdOverridableVariables = NULL; - m_pTaskbarList = NULL; - m_uTaskbarButtonCreatedMessage = UINT_MAX; - m_fTaskbarButtonOK = FALSE; - m_fShowingInternalUiThisPackage = FALSE; - - m_fPrereq = fPrereq; - m_sczPrereqPackage = NULL; - m_fPrereqInstalled = FALSE; - m_fPrereqAlreadyInstalled = FALSE; - m_fOverallInstallationStarted = FALSE; - m_fUpdating = FALSE; - - pEngine->AddRef(); - m_pEngine = pEngine; - - m_hBAFModule = NULL; - m_pBAFunction = NULL; - } - - - // - // Destructor - release member variables. - // - ~CWixStandardBootstrapperApplication() - { - CopyBundleLogToSpecifiedPath(); - AssertSz(!::IsWindow(m_hWnd), "Window should have been destroyed before destructor."); - AssertSz(!m_pTheme, "Theme should have been released before destuctor."); - - ReleaseObject(m_pTaskbarList); - ReleaseDict(m_sdOverridableVariables); - ReleaseStr(m_sczFailedMessage); - ReleaseStr(m_sczConfirmCloseMessage); - BalConditionsUninitialize(&m_Conditions); - BalInfoUninitialize(&m_Bundle); - LocFree(m_pWixLoc); - - ReleaseStr(m_sczLanguage); - ReleaseStr(m_sczLicenseFile); - ReleaseStr(m_sczLicenseUrl); - ReleaseStr(m_sczPrereqPackage); - ReleaseStr(m_sczAfterForcedRestartPackage); - ReleaseNullObject(m_pEngine); - - if (m_hBAFModule) - { - ::FreeLibrary(m_hBAFModule); - m_hBAFModule = NULL; - } - } - -private: - HMODULE m_hModule; - BOOTSTRAPPER_COMMAND m_command; - IBootstrapperEngine* m_pEngine; - BOOTSTRAPPER_ACTION m_plannedAction; - - LPWSTR m_sczAfterForcedRestartPackage; - - WIX_LOCALIZATION* m_pWixLoc; - BAL_INFO_BUNDLE m_Bundle; - BAL_CONDITIONS m_Conditions; - LPWSTR m_sczFailedMessage; - LPWSTR m_sczConfirmCloseMessage; - - LPWSTR m_sczLanguage; - THEME* m_pTheme; - DWORD m_rgdwPageIds[countof(vrgwzPageNames)]; - DWORD m_dwCurrentPage; - HANDLE m_hUiThread; - BOOL m_fRegistered; - HWND m_hWnd; - - WIXSTDBA_STATE m_state; - WIXSTDBA_STATE m_stateInstallPage; - HRESULT m_hrFinal; - - BOOL m_fStartedExecution; - DWORD m_dwCalculatedCacheProgress; - DWORD m_dwCalculatedExecuteProgress; - - BOOL m_fDowngrading; - BOOTSTRAPPER_APPLY_RESTART m_restartResult; - BOOL m_fRestartRequired; - BOOL m_fAllowRestart; - - LPWSTR m_sczLicenseFile; - LPWSTR m_sczLicenseUrl; - BOOL m_fSuppressOptionsUI; - BOOL m_fSuppressDowngradeFailure; - BOOL m_fSuppressRepair; - BOOL m_fShowVersion; - BOOL m_fIsRepair; - BOOL m_fIsUninstall; - BOOL m_fInstallSucceed; - - BOOTSTRAPPER_RELATED_OPERATION m_Operation; - - BOOL m_fIsProductCore; - BOOL m_fOverallInstallationStarted; - - - STRINGDICT_HANDLE m_sdOverridableVariables; - - BOOL m_fPrereq; - LPWSTR m_sczPrereqPackage; - BOOL m_fPrereqInstalled; - BOOL m_fPrereqAlreadyInstalled; - - ITaskbarList3* m_pTaskbarList; - UINT m_uTaskbarButtonCreatedMessage; - BOOL m_fTaskbarButtonOK; - BOOL m_fShowingInternalUiThisPackage; - - BOOL m_fUpdating; - LPCWSTR m_wzUpdateLocation; - - HMODULE m_hBAFModule; - IBootstrapperBAFunction* m_pBAFunction; -}; - - -// -// CreateUserExperience - creates a new IBurnUserExperience object. -// -HRESULT CreateBootstrapperApplication( - __in HMODULE hModule, - __in BOOL fPrereq, - __in IBootstrapperEngine* pEngine, - __in const BOOTSTRAPPER_COMMAND* pCommand, - __out IBootstrapperApplication** ppApplication - ) -{ - HRESULT hr = S_OK; - CWixStandardBootstrapperApplication* pApplication = NULL; - - pApplication = new CWixStandardBootstrapperApplication(hModule, fPrereq, pEngine, pCommand); - ExitOnNull(pApplication, hr, E_OUTOFMEMORY, "Failed to create new standard bootstrapper application object."); - - *ppApplication = pApplication; - pApplication = NULL; - -LExit: - ReleaseObject(pApplication); - return hr; -} +//------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2004, Outercurve Foundation. +// This software is released under Microsoft Reciprocal License (MS-RL). +// The license and further copyright text can be found in the file +// LICENSE.TXT at the root directory of the distribution. +// +//------------------------------------------------------------------------------------------------- + + +#include "precomp.h" +#include "regutil.h" +#include "JSON.h" + + +static const HRESULT E_WIXSTDBA_CONDITION_FAILED = MAKE_HRESULT(SEVERITY_ERROR, 500, 1); + +static const LPCWSTR WIXBUNDLE_VARIABLE_ELEVATED = L"WixBundleElevated"; + +static const LPCWSTR WIXSTDBA_WINDOW_CLASS = L"WixExtBA"; +static const LPCWSTR WIXSTDBA_VARIABLE_INSTALL_FOLDER = L"InstallFolder"; +static const LPCWSTR WIXSTDBA_VARIABLE_INSTALL_REGPATH = L"InstallRegPath"; +static const LPCWSTR WIXSTDBA_VARIABLE_LAUNCH_TARGET_PATH = L"LaunchTarget"; +static const LPCWSTR WIXSTDBA_VARIABLE_LAUNCH_ARGUMENTS = L"LaunchArguments"; +static const LPCWSTR WIXSTDBA_VARIABLE_LAUNCH_HIDDEN = L"LaunchHidden"; +static const LPCWSTR WIXSTDBA_VARIABLE_LAUNCHAFTERINSTALL_TARGET_PATH = L"LaunchAfterInstallTarget"; +static const LPCWSTR WIXSTDBA_VARIABLE_LAUNCHAFTERINSTALL_ARGUMENTS = L"LaunchAfterInstallArguments"; + +static const LPCWSTR WIXSTDBA_VARIABLE_PROGRESS_HEADER = L"varProgressHeader"; +static const LPCWSTR WIXSTDBA_VARIABLE_PROGRESS_INFO = L"varProgressInfo"; +static const LPCWSTR WIXSTDBA_VARIABLE_SUCCESS_HEADER = L"varSuccessHeader"; +static const LPCWSTR WIXSTDBA_VARIABLE_SUCCESS_INFO = L"varSuccessInfo"; +static const LPCWSTR WIXSTDBA_VARIABLE_FAILURE_HEADER = L"varFailureHeader"; +static const LPCWSTR WIXSTDBA_VARIABLE_SUCCESS_ERRINF = L"varSuccessErrorInfoText"; +static const LPCWSTR WIXSTDBA_VARIABLE_SUCCESS_ERRMSG = L"varSuccessErrorMessageText"; + +static const LPCWSTR WIXSTDBA_VARIABLE_PERMACHINE_INSTALL = L"PerMachineInstall"; +static const LPCWSTR WIXSTDBA_VARIABLE_PERMACHINE_INSTALL_FOLDER = L"PerMachineInstallFolder"; +static const LPCWSTR WIXSTDBA_VARIABLE_PERUSER_INSTALL_FOLDER = L"PerUserInstallFolder"; +static const LPCWSTR WIXSTDBA_VARIABLE_USERMETEORSESSIONFILE = L"UserMeteorSessionFile"; + + +static const LPCWSTR WIXSTDBA_VARIABLE_REG_MAIL = L"RegisterEmail"; +static const LPCWSTR WIXSTDBA_VARIABLE_REG_USER = L"RegisterUser"; +static const LPCWSTR WIXSTDBA_VARIABLE_REG_PASS = L"RegisterPass"; + + + +static const LPCWSTR WIXSTDBA_VARIABLE_LOGSPATH = L"QCInstallLogsPath"; + +static const DWORD WIXSTDBA_ACQUIRE_PERCENTAGE = 1; + +enum WIXSTDBA_STATE +{ + WIXSTDBA_STATE_INSTALLDIR, + WIXSTDBA_STATE_SVC_OPTIONS, + WIXSTDBA_STATE_INITIALIZING, + WIXSTDBA_STATE_INITIALIZED, + WIXSTDBA_STATE_HELP, + WIXSTDBA_STATE_DETECTING, + WIXSTDBA_STATE_DETECTED, + WIXSTDBA_STATE_PLANNING, + WIXSTDBA_STATE_PLANNED, + WIXSTDBA_STATE_APPLYING, + WIXSTDBA_STATE_CACHING, + WIXSTDBA_STATE_CACHED, + WIXSTDBA_STATE_EXECUTING, + WIXSTDBA_STATE_EXECUTED, + WIXSTDBA_STATE_APPLIED, + WIXSTDBA_STATE_FAILED, +}; + +enum WM_WIXSTDBA +{ + WM_WIXSTDBA_SHOW_HELP = WM_APP + 100, + WM_WIXSTDBA_DETECT_PACKAGES, + WM_WIXSTDBA_PLAN_PACKAGES, + WM_WIXSTDBA_APPLY_PACKAGES, + WM_WIXSTDBA_CHANGE_STATE, +}; + +// This enum must be kept in the same order as the vrgwzPageNames array. +enum WIXSTDBA_PAGE +{ + WIXSTDBA_PAGE_LOADING, + WIXSTDBA_PAGE_HELP, + WIXSTDBA_PAGE_INSTALL, + WIXSTDBA_PAGE_INSTALLDIR, + WIXSTDBA_PAGE_SVC_OPTIONS, + WIXSTDBA_PAGE_MODIFY, + WIXSTDBA_PAGE_PROGRESS, + WIXSTDBA_PAGE_PROGRESS_PASSIVE, + WIXSTDBA_PAGE_SUCCESS, + WIXSTDBA_PAGE_FAILURE, + COUNT_WIXSTDBA_PAGE, +}; + +// This array must be kept in the same order as the WIXSTDBA_PAGE enum. +static LPCWSTR vrgwzPageNames[] = { + L"Loading", + L"Help", + L"Install", + L"InstallDir", + L"SvcOptions", + L"Modify", + L"Progress", + L"ProgressPassive", + L"Success", + L"Failure", +}; + +enum WIXSTDBA_CONTROL +{ + // Non-paged controls + WIXSTDBA_CONTROL_CLOSE_BUTTON = THEME_FIRST_ASSIGN_CONTROL_ID, + WIXSTDBA_CONTROL_MINIMIZE_BUTTON, + + // Help page + WIXSTDBA_CONTROL_HELP_CANCEL_BUTTON, + + // Welcome page + WIXSTDBA_CONTROL_INSTALL_BUTTON, + WIXSTDBA_CONTROL_OPTIONS_BUTTON, + WIXSTDBA_CONTROL_EULA_RICHEDIT, + WIXSTDBA_CONTROL_EULA_LINK, + WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX, + WIXSTDBA_CONTROL_WELCOME_CANCEL_BUTTON, + WIXSTDBA_CONTROL_VERSION_LABEL, + WIXSTDBA_CONTROL_UPGRADE_LINK, + WIXSTDBA_CONTROL_NEXT_BUTTON, + WIXSTDBA_CONTROL_BACK_BUTTON, + + + // Options page + WIXSTDBA_CONTROL_PERMACHINE_RADIO, + WIXSTDBA_CONTROL_PERUSER_RADIO, + WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX, + WIXSTDBA_CONTROL_BROWSE_BUTTON, + + WIXSTDBA_CONTROL_REGSIGNIN_RADIO, + WIXSTDBA_CONTROL_REGCREATE_RADIO, + WIXSTDBA_CONTROL_REGMAIL_LABEL, + WIXSTDBA_CONTROL_REGUSER_LABEL, + WIXSTDBA_CONTROL_REGPASS_LABEL, + WIXSTDBA_CONTROL_REGMAIL_EDIT, + WIXSTDBA_CONTROL_REGUSER_EDIT, + WIXSTDBA_CONTROL_REGPASS_EDIT, + WIXSTDBA_CONTROL_SKIPREG_CHECKBOX, + + + WIXSTDBA_CONTROL_OK_BUTTON, + WIXSTDBA_CONTROL_CANCEL_BUTTON, + + // Modify page + WIXSTDBA_CONTROL_REPAIR_BUTTON, + WIXSTDBA_CONTROL_UNINSTALL_BUTTON, + WIXSTDBA_CONTROL_MODIFY_CANCEL_BUTTON, + + // Progress page + WIXSTDBA_CONTROL_CACHE_PROGRESS_PACKAGE_TEXT, + WIXSTDBA_CONTROL_CACHE_PROGRESS_BAR, + WIXSTDBA_CONTROL_CACHE_PROGRESS_TEXT, + + WIXSTDBA_CONTROL_EXECUTE_PROGRESS_PACKAGE_TEXT, + WIXSTDBA_CONTROL_EXECUTE_PROGRESS_BAR, + WIXSTDBA_CONTROL_EXECUTE_PROGRESS_TEXT, + WIXSTDBA_CONTROL_EXECUTE_PROGRESS_ACTIONDATA_TEXT, + + WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, + WIXSTDBA_CONTROL_OVERALL_PROGRESS_BAR, + WIXSTDBA_CONTROL_OVERALL_CALCULATED_PROGRESS_BAR, + WIXSTDBA_CONTROL_OVERALL_PROGRESS_TEXT, + + WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, + + // Success page + WIXSTDBA_CONTROL_LAUNCH_BUTTON, + WIXSTDBA_CONTROL_SUCCESS_RESTART_TEXT, + WIXSTDBA_CONTROL_SUCCESS_RESTART_BUTTON, + WIXSTDBA_CONTROL_SUCCESS_CANCEL_BUTTON, + WIXSTDBA_CONTROL_SUCCESS_ERRINF_TEXT, + WIXSTDBA_CONTROL_SUCCESS_ERRMSG_TEXT, + + // Failure page + WIXSTDBA_CONTROL_FAILURE_LOGFILE_LINK, + WIXSTDBA_CONTROL_FAILURE_MESSAGE_TEXT, + WIXSTDBA_CONTROL_FAILURE_RESTART_TEXT, + WIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON, + WIXSTDBA_CONTROL_FAILURE_CANCEL_BUTTON, +}; + +static THEME_ASSIGN_CONTROL_ID vrgInitControls[] = { + { WIXSTDBA_CONTROL_CLOSE_BUTTON, L"CloseButton" }, + { WIXSTDBA_CONTROL_MINIMIZE_BUTTON, L"MinimizeButton" }, + + { WIXSTDBA_CONTROL_HELP_CANCEL_BUTTON, L"HelpCancelButton" }, + + { WIXSTDBA_CONTROL_INSTALL_BUTTON, L"InstallButton" }, + { WIXSTDBA_CONTROL_OPTIONS_BUTTON, L"OptionsButton" }, + { WIXSTDBA_CONTROL_EULA_RICHEDIT, L"EulaRichedit" }, + { WIXSTDBA_CONTROL_EULA_LINK, L"EulaHyperlink" }, + { WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX, L"EulaAcceptCheckbox" }, + { WIXSTDBA_CONTROL_WELCOME_CANCEL_BUTTON, L"WelcomeCancelButton" }, + { WIXSTDBA_CONTROL_VERSION_LABEL, L"InstallVersion" }, + { WIXSTDBA_CONTROL_UPGRADE_LINK, L"UpgradeHyperlink" }, + { WIXSTDBA_CONTROL_NEXT_BUTTON, L"NextButton" }, + { WIXSTDBA_CONTROL_BACK_BUTTON, L"BackButton" }, + + {WIXSTDBA_CONTROL_PERMACHINE_RADIO, L"PerMachineInstall" }, + {WIXSTDBA_CONTROL_PERUSER_RADIO, L"PerUserInstall" }, + { WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX, L"InstallFolderEditbox" }, + { WIXSTDBA_CONTROL_BROWSE_BUTTON, L"BrowseButton" }, + + {WIXSTDBA_CONTROL_REGSIGNIN_RADIO, L"SignInRButton"}, + {WIXSTDBA_CONTROL_REGCREATE_RADIO, L"CreateRButton"}, + {WIXSTDBA_CONTROL_REGMAIL_LABEL, L"RegisterEmailLabel"}, + {WIXSTDBA_CONTROL_REGUSER_LABEL, L"RegisterUserLabel"}, + {WIXSTDBA_CONTROL_REGPASS_LABEL, L"RegisterPassLabel"}, + {WIXSTDBA_CONTROL_REGMAIL_EDIT, L"RegisterEmail"}, + {WIXSTDBA_CONTROL_REGUSER_EDIT, L"RegisterUser"}, + {WIXSTDBA_CONTROL_REGPASS_EDIT, L"RegisterPass"}, + {WIXSTDBA_CONTROL_SKIPREG_CHECKBOX, L"SkipRegistration"}, + + { WIXSTDBA_CONTROL_REPAIR_BUTTON, L"RepairButton" }, + { WIXSTDBA_CONTROL_UNINSTALL_BUTTON, L"UninstallButton" }, + { WIXSTDBA_CONTROL_MODIFY_CANCEL_BUTTON, L"ModifyCancelButton" }, + + { WIXSTDBA_CONTROL_CACHE_PROGRESS_PACKAGE_TEXT, L"CacheProgressPackageText" }, + { WIXSTDBA_CONTROL_CACHE_PROGRESS_BAR, L"CacheProgressbar" }, + { WIXSTDBA_CONTROL_CACHE_PROGRESS_TEXT, L"CacheProgressText" }, + { WIXSTDBA_CONTROL_EXECUTE_PROGRESS_PACKAGE_TEXT, L"ExecuteProgressPackageText" }, + { WIXSTDBA_CONTROL_EXECUTE_PROGRESS_BAR, L"ExecuteProgressbar" }, + { WIXSTDBA_CONTROL_EXECUTE_PROGRESS_TEXT, L"ExecuteProgressText" }, + { WIXSTDBA_CONTROL_EXECUTE_PROGRESS_ACTIONDATA_TEXT, L"ExecuteProgressActionDataText"}, + { WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, L"OverallProgressPackageText" }, + { WIXSTDBA_CONTROL_OVERALL_PROGRESS_BAR, L"OverallProgressbar" }, + { WIXSTDBA_CONTROL_OVERALL_CALCULATED_PROGRESS_BAR, L"OverallCalculatedProgressbar" }, + { WIXSTDBA_CONTROL_OVERALL_PROGRESS_TEXT, L"OverallProgressText" }, + { WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, L"ProgressCancelButton" }, + + { WIXSTDBA_CONTROL_LAUNCH_BUTTON, L"LaunchButton" }, + { WIXSTDBA_CONTROL_SUCCESS_RESTART_TEXT, L"SuccessRestartText" }, + { WIXSTDBA_CONTROL_SUCCESS_RESTART_BUTTON, L"SuccessRestartButton" }, + { WIXSTDBA_CONTROL_SUCCESS_CANCEL_BUTTON, L"SuccessCancelButton" }, + { WIXSTDBA_CONTROL_SUCCESS_ERRINF_TEXT, L"SuccessErrorInfoText" }, + { WIXSTDBA_CONTROL_SUCCESS_ERRMSG_TEXT, L"SuccessErrorMessageText" }, + + { WIXSTDBA_CONTROL_FAILURE_LOGFILE_LINK, L"FailureLogFileLink" }, + { WIXSTDBA_CONTROL_FAILURE_MESSAGE_TEXT, L"FailureMessageText" }, + { WIXSTDBA_CONTROL_FAILURE_RESTART_TEXT, L"FailureRestartText" }, + { WIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON, L"FailureRestartButton" }, + { WIXSTDBA_CONTROL_FAILURE_CANCEL_BUTTON, L"FailureCloseButton" }, +}; + + +void ExtractActionProgressText( + __in_z LPCWSTR wzActionMessage, + __in_z LPCWSTR *pwzActionProgressText + ) +{ + if (!wzActionMessage) + return; + + DWORD i = 0; + LPCWSTR wzActionProgressText = wzActionMessage; + + LPCWSTR wz = wzActionMessage; + while (*wz) + { + if (L' ' == *wz) ++i; + if (i <= 2) wzActionProgressText++; + + ++wz; + } + *pwzActionProgressText = wzActionProgressText; + + return; +} + + + + +class CWixStandardBootstrapperApplication : public CBalBaseBootstrapperApplication +{ +public: // IBootstrapperApplication + virtual STDMETHODIMP OnStartup() + { + HRESULT hr = S_OK; + DWORD dwUIThreadId = 0; + + // create UI thread + m_hUiThread = ::CreateThread(NULL, 0, UiThreadProc, this, 0, &dwUIThreadId); + if (!m_hUiThread) + { + ExitWithLastError(hr, "Failed to create UI thread."); + } + +LExit: + return hr; + } + + + virtual STDMETHODIMP_(int) OnShutdown() + { + int nResult = IDNOACTION; + + // wait for UI thread to terminate + if (m_hUiThread) + { + ::WaitForSingleObject(m_hUiThread, INFINITE); + ReleaseHandle(m_hUiThread); + } + + // If a restart was required. + if (m_fRestartRequired) + { + if (m_fAllowRestart) + { + nResult = IDRESTART; + } + + if (m_sczPrereqPackage) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, m_fAllowRestart ? "The prerequisites scheduled a restart. The bootstrapper application will be reloaded after the computer is restarted." + : "A restart is required by the prerequisites but the user delayed it. The bootstrapper application will be reloaded after the computer is restarted."); + } + } + else if (m_fPrereqInstalled) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "The prerequisites were successfully installed. The bootstrapper application will be reloaded."); + nResult = IDRELOAD_BOOTSTRAPPER; + } + else if (m_fPrereqAlreadyInstalled) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "The prerequisites were already installed. The bootstrapper application will not be reloaded to prevent an infinite loop."); + } + else if (m_fPrereq) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "The prerequisites were not successfully installed, error: 0x%x. The bootstrapper application will be not reloaded.", m_hrFinal); + } + + return nResult; + } + + + virtual STDMETHODIMP_(int) OnDetectRelatedBundle( + __in LPCWSTR wzBundleId, + __in BOOTSTRAPPER_RELATION_TYPE relationType, + __in LPCWSTR /*wzBundleTag*/, + __in BOOL fPerMachine, + __in DWORD64 /*dw64Version*/, + __in BOOTSTRAPPER_RELATED_OPERATION operation + ) + { + BalInfoAddRelatedBundleAsPackage(&m_Bundle.packages, wzBundleId, relationType, fPerMachine); + // If we're not doing a pre-req install, remember when our bundle would cause a downgrade. + if (!m_sczPrereqPackage && BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE == operation) + { + m_fDowngrading = TRUE; + } + + m_Operation = operation; // Save operation + + return CheckCanceled() ? IDCANCEL : IDOK; + } + + + virtual STDMETHODIMP_(void) OnDetectPackageComplete( + __in LPCWSTR wzPackageId, + __in HRESULT /*hrStatus*/, + __in BOOTSTRAPPER_PACKAGE_STATE state + ) + { + // If the prereq package is already installed, remember that. + if (m_sczPrereqPackage && BOOTSTRAPPER_PACKAGE_STATE_PRESENT == state && + CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzPackageId, -1, m_sczPrereqPackage, -1)) + { + m_fPrereqAlreadyInstalled = TRUE; + } + } + + + // OnDetectUpdateBegin - called when the engine begins detection for bundle update. + virtual STDMETHODIMP_(int) OnDetectUpdateBegin( + __in_z LPCWSTR wzUpdateLocation, + __in int nRecommendation + ) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Update location: %ls.", wzUpdateLocation); + + m_wzUpdateLocation = wzUpdateLocation; + // If there is an upgrade link, check for update on a background thread + if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_UPGRADE_LINK)) + { + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_UPGRADE_LINK, FALSE); + ::CreateThread(NULL, 0, ThreadProc, this, 0, NULL); + } + + return nRecommendation; + } + + + virtual STDMETHODIMP_(int) OnDetectBegin( + __in BOOL /*fInstalled*/, + __in DWORD /*cPackages*/ + ) + { + return IDNOACTION; + } + + + virtual STDMETHODIMP_(void) OnDetectComplete( + __in HRESULT hrStatus + ) + { + if (SUCCEEDED(hrStatus) && m_pBAFunction) + { + m_pBAFunction->OnDetectComplete(); + } + + if (SUCCEEDED(hrStatus)) + { + hrStatus = EvaluateConditions(); + } + + SetState(WIXSTDBA_STATE_DETECTED, hrStatus); + + // Doing some custom vars handling + //if (BalStringVariableExists(WIXSTDBA_VARIABLE_DETECT_POSTGRES)) + //{ + // LONGLONG llValue = 0; + // BalGetNumericVariable(WIXSTDBA_VARIABLE_DETECT_POSTGRES, &llValue); + // if (llValue == 1) + // m_pEngine->SetVariableNumeric(WIXSTDBA_VARIABLE_INSTALL_POSTGRES, 0); + //} + + + // If we're not interacting with the user or we're doing a layout or we're just after a force restart + // then automatically start planning. + if (BOOTSTRAPPER_DISPLAY_FULL > m_command.display || BOOTSTRAPPER_ACTION_LAYOUT == m_command.action || BOOTSTRAPPER_RESUME_TYPE_REBOOT == m_command.resumeType) + { + if (SUCCEEDED(hrStatus)) + { + ::PostMessageW(m_hWnd, WM_WIXSTDBA_PLAN_PACKAGES, 0, m_command.action); + } + } + } + + + virtual STDMETHODIMP_(int) OnPlanRelatedBundle( + __in_z LPCWSTR /*wzBundleId*/, + __inout_z BOOTSTRAPPER_REQUEST_STATE* pRequestedState + ) + { + // If we're only installing prereq, do not touch related bundles. + if (m_sczPrereqPackage) + { + *pRequestedState = BOOTSTRAPPER_REQUEST_STATE_NONE; + } + else if (BOOTSTRAPPER_RELATED_OPERATION_NONE == m_Operation && + BOOTSTRAPPER_REQUEST_STATE_NONE == *pRequestedState && + BOOTSTRAPPER_RELATION_UPGRADE != m_command.relationType) + { + // Same version upgrade detected, mark absent so the install runs + *pRequestedState = BOOTSTRAPPER_REQUEST_STATE_ABSENT; + } + + return CheckCanceled() ? IDCANCEL : IDOK; + } + + + virtual STDMETHODIMP_(int) OnPlanPackageBegin( + __in_z LPCWSTR wzPackageId, + __inout BOOTSTRAPPER_REQUEST_STATE *pRequestState + ) + { + // If we're planning to install a pre-req, install it. The pre-req needs to be installed + // in all cases (even uninstall!) so the BA can load next. + if (m_sczPrereqPackage) + { + if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzPackageId, -1, m_sczPrereqPackage, -1)) + { + *pRequestState = BOOTSTRAPPER_REQUEST_STATE_PRESENT; + } + else // skip everything else. + { + *pRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE; + } + } + else if (m_sczAfterForcedRestartPackage) // after force restart skip packages until after the package that caused the restart. + { + // After restart we need to finish the dependency registration for our package so allow the package + // to go present. + if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzPackageId, -1, m_sczAfterForcedRestartPackage, -1)) + { + // Do not allow a repair because that could put us in a perpetual restart loop. + if (BOOTSTRAPPER_REQUEST_STATE_REPAIR == *pRequestState) + { + *pRequestState = BOOTSTRAPPER_REQUEST_STATE_PRESENT; + } + + ReleaseNullStr(m_sczAfterForcedRestartPackage); // no more skipping now. + } + else // not the matching package, so skip it. + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Skipping package: %ls, after restart because it was applied before the restart.", wzPackageId); + + *pRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE; + } + } + + return CheckCanceled() ? IDCANCEL : IDOK; + } + + + virtual STDMETHODIMP_(void) OnPlanComplete( + __in HRESULT hrStatus + ) + { + if (SUCCEEDED(hrStatus) && m_pBAFunction) + { + m_pBAFunction->OnPlanComplete(); + } + + SetState(WIXSTDBA_STATE_PLANNED, hrStatus); + + if (SUCCEEDED(hrStatus)) + { + ::PostMessageW(m_hWnd, WM_WIXSTDBA_APPLY_PACKAGES, 0, 0); + } + + m_fStartedExecution = FALSE; + m_dwCalculatedCacheProgress = 0; + m_dwCalculatedExecuteProgress = 0; + } + + + virtual STDMETHODIMP_(int) OnCachePackageBegin( + __in_z LPCWSTR wzPackageId, + __in DWORD cCachePayloads, + __in DWORD64 dw64PackageCacheSize + ) + { + if (wzPackageId && *wzPackageId) + { + BAL_INFO_PACKAGE* pPackage = NULL; + HRESULT hr = BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage); + LPCWSTR wz = (SUCCEEDED(hr) && pPackage->sczDisplayName) ? pPackage->sczDisplayName : wzPackageId; + + WCHAR wzInfo[1024] = { }; + ::StringCchPrintfW(wzInfo, countof(wzInfo), L"Acquiring %s package...", wz); + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_CACHE_PROGRESS_PACKAGE_TEXT, wzInfo); + // If something started executing, leave it in the overall progress text. + if (!m_fStartedExecution) + { + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, wzInfo); + } + } + + return __super::OnCachePackageBegin(wzPackageId, cCachePayloads, dw64PackageCacheSize); + } + + virtual STDMETHODIMP_(int) OnCacheAcquireProgress( + __in_z LPCWSTR wzPackageOrContainerId, + __in_z_opt LPCWSTR wzPayloadId, + __in DWORD64 dw64Progress, + __in DWORD64 dw64Total, + __in DWORD dwOverallPercentage + ) + { + WCHAR wzProgress[5] = { }; + +#ifdef DEBUG + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: OnCacheAcquireProgress() - container/package: %ls, payload: %ls, progress: %I64u, total: %I64u, overall progress: %u%%", wzPackageOrContainerId, wzPayloadId, dw64Progress, dw64Total, dwOverallPercentage); +#endif + + ::StringCchPrintfW(wzProgress, countof(wzProgress), L"%u%%", dwOverallPercentage); + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_CACHE_PROGRESS_TEXT, wzProgress); + ThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_CACHE_PROGRESS_BAR, dwOverallPercentage); + + BAL_INFO_PACKAGE* pPackage = NULL; + HRESULT hr = BalInfoFindPackageById(&m_Bundle.packages, wzPackageOrContainerId, &pPackage); + LPCWSTR wzPackageName = (SUCCEEDED(hr) && pPackage->sczDisplayName) ? pPackage->sczDisplayName : wzPackageOrContainerId; + + WCHAR wzInfo[1024] = { }; + ::StringCchPrintfW(wzInfo, countof(wzInfo), L"Acquiring %s package... [ %u%% ]", wzPackageName, dwOverallPercentage); + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, wzInfo); + + // Restrict progress to 100% to hide burn engine progress bug. + // m_dwCalculatedCacheProgress = min(dwOverallPercentage, 100) * WIXSTDBA_ACQUIRE_PERCENTAGE / 100; + +#ifdef DEBUG + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: OnCacheAcquireProgress() - calculated progress: %u%%, displayed progress: %u%%", m_dwCalculatedCacheProgress, m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress); +#endif + m_dwCalculatedCacheProgress = dwOverallPercentage * WIXSTDBA_ACQUIRE_PERCENTAGE / 100; + ThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_CALCULATED_PROGRESS_BAR, m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress); + + SetTaskbarButtonProgress(m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress); + + return __super::OnCacheAcquireProgress(wzPackageOrContainerId, wzPayloadId, dw64Progress, dw64Total, dwOverallPercentage); + } + + + virtual STDMETHODIMP_(int) OnCacheAcquireComplete( + __in_z LPCWSTR wzPackageOrContainerId, + __in_z_opt LPCWSTR wzPayloadId, + __in HRESULT hrStatus, + __in int nRecommendation + ) + { + SetProgressState(hrStatus); + return __super::OnCacheAcquireComplete(wzPackageOrContainerId, wzPayloadId, hrStatus, nRecommendation); + } + + + virtual STDMETHODIMP_(int) OnCacheVerifyComplete( + __in_z LPCWSTR wzPackageId, + __in_z LPCWSTR wzPayloadId, + __in HRESULT hrStatus, + __in int nRecommendation + ) + { + SetProgressState(hrStatus); + return __super::OnCacheVerifyComplete(wzPackageId, wzPayloadId, hrStatus, nRecommendation); + } + + virtual STDMETHODIMP_(void) OnCacheComplete( + __in HRESULT /*hrStatus*/ + ) + { + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_CACHE_PROGRESS_PACKAGE_TEXT, L""); + SetState(WIXSTDBA_STATE_CACHED, S_OK); // we always return success here and let OnApplyComplete() deal with the error. + } + + + virtual STDMETHODIMP_(int) OnError( + __in BOOTSTRAPPER_ERROR_TYPE errorType, + __in LPCWSTR wzPackageId, + __in DWORD dwCode, + __in_z LPCWSTR wzError, + __in DWORD dwUIHint, + __in DWORD /*cData*/, + __in_ecount_z_opt(cData) LPCWSTR* /*rgwzData*/, + __in int nRecommendation + ) + { + int nResult = nRecommendation; + LPWSTR sczError = NULL; + + if (BOOTSTRAPPER_DISPLAY_EMBEDDED == m_command.display) + { + HRESULT hr = m_pEngine->SendEmbeddedError(dwCode, wzError, dwUIHint, &nResult); + if (FAILED(hr)) + { + nResult = IDERROR; + } + } + else if (BOOTSTRAPPER_DISPLAY_FULL == m_command.display) + { + // If this is an authentication failure, let the engine try to handle it for us. + if (BOOTSTRAPPER_ERROR_TYPE_HTTP_AUTH_SERVER == errorType || BOOTSTRAPPER_ERROR_TYPE_HTTP_AUTH_PROXY == errorType) + { + nResult = IDTRYAGAIN; + } + else // show a generic error message box. + { + BalRetryErrorOccurred(wzPackageId, dwCode); + + if (!m_fShowingInternalUiThisPackage) + { + // If no error message was provided, use the error code to try and get an error message. + if (!wzError || !*wzError || BOOTSTRAPPER_ERROR_TYPE_WINDOWS_INSTALLER != errorType) + { + HRESULT hr = StrAllocFromError(&sczError, dwCode, NULL); + if (FAILED(hr) || !sczError || !*sczError) + { + StrAllocFormatted(&sczError, L"0x%x", dwCode); + } + } + + nResult = ::MessageBoxW(m_hWnd, sczError ? sczError : wzError, m_pTheme->sczCaption, dwUIHint); + } + } + + SetProgressState(HRESULT_FROM_WIN32(dwCode)); + } + else // just take note of the error code and let things continue. + { + BalRetryErrorOccurred(wzPackageId, dwCode); + } + + ReleaseStr(sczError); + return nResult; + } + + + virtual STDMETHODIMP_(int) OnExecuteMsiMessage( + __in_z LPCWSTR wzPackageId, + __in INSTALLMESSAGE mt, + __in UINT uiFlags, + __in_z LPCWSTR wzMessage, + __in DWORD cData, + __in_ecount_z_opt(cData) LPCWSTR* rgwzData, + __in int nRecommendation + ) + { +#ifdef DEBUG + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: OnExecuteMsiMessage() - package: %ls, message: %ls", wzPackageId, wzMessage); +#endif + if (BOOTSTRAPPER_DISPLAY_FULL == m_command.display && (INSTALLMESSAGE_WARNING == mt || INSTALLMESSAGE_USER == mt)) + { + int nResult = ::MessageBoxW(m_hWnd, wzMessage, m_pTheme->sczCaption, uiFlags); + return nResult; + } + + if (INSTALLMESSAGE_ACTIONSTART == mt) + { + LPCWSTR wzActionProgressText = NULL; + ExtractActionProgressText(wzMessage, &wzActionProgressText); + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_ACTIONDATA_TEXT, wzActionProgressText); + } + + return __super::OnExecuteMsiMessage(wzPackageId, mt, uiFlags, wzMessage, cData, rgwzData, nRecommendation); + } + + + virtual STDMETHODIMP_(int) OnProgress( + __in DWORD dwProgressPercentage, + __in DWORD dwOverallProgressPercentage + ) + { + WCHAR wzProgress[5] = { }; + +#ifdef DEBUG + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: OnProgress() - progress: %u%%, overall progress: %u%%", dwProgressPercentage, dwOverallProgressPercentage); +#endif + + ::StringCchPrintfW(wzProgress, countof(wzProgress), L"%u%%", dwOverallProgressPercentage); + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_TEXT, wzProgress); + + ThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_BAR, dwOverallProgressPercentage); + SetTaskbarButtonProgress(dwOverallProgressPercentage); + + return __super::OnProgress(dwProgressPercentage, dwOverallProgressPercentage); + } + + + virtual STDMETHODIMP_(int) OnExecutePackageBegin( + __in_z LPCWSTR wzPackageId, + __in BOOL fExecute + ) + { + LPWSTR sczFormattedString = NULL; + + m_fStartedExecution = TRUE; + + if (wzPackageId && *wzPackageId) + { + BAL_INFO_PACKAGE* pPackage = NULL; + BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage); + + LPCWSTR wz = wzPackageId; + if (pPackage) + { + LOC_STRING* pLocString = NULL; + + switch (pPackage->type) + { + case BAL_INFO_PACKAGE_TYPE_BUNDLE_ADDON: + LocGetString(m_pWixLoc, L"#(loc.ExecuteAddonRelatedBundleMessage)", &pLocString); + break; + + case BAL_INFO_PACKAGE_TYPE_BUNDLE_PATCH: + LocGetString(m_pWixLoc, L"#(loc.ExecutePatchRelatedBundleMessage)", &pLocString); + break; + + case BAL_INFO_PACKAGE_TYPE_BUNDLE_UPGRADE: + LocGetString(m_pWixLoc, L"#(loc.ExecuteUpgradeRelatedBundleMessage)", &pLocString); + break; + } + + if (pLocString) + { + BalFormatString(pLocString->wzText, &sczFormattedString); + } + + wz = sczFormattedString ? sczFormattedString : pPackage->sczDisplayName ? pPackage->sczDisplayName : wzPackageId; + } + + m_fShowingInternalUiThisPackage = pPackage && pPackage->fDisplayInternalUI; + + WCHAR wzInfo[1024] = { }; + if (m_fIsUninstall) + ::StringCchPrintfW(wzInfo, countof(wzInfo), L"Uninstalling %s ...", wz); + else + ::StringCchPrintfW(wzInfo, countof(wzInfo), L"Installing %s ...", wz); + + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_PACKAGE_TEXT, wz); + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, wz); + } + else + { + m_fShowingInternalUiThisPackage = FALSE; + } + + ReleaseStr(sczFormattedString); + return __super::OnExecutePackageBegin(wzPackageId, fExecute); + } + + virtual int __stdcall OnExecuteProgress( + __in_z LPCWSTR wzPackageId, + __in DWORD dwProgressPercentage, + __in DWORD dwOverallProgressPercentage + ) + { + WCHAR wzProgress[5] = { }; + +#ifdef DEBUG + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: OnExecuteProgress() - package: %ls, progress: %u%%, overall progress: %u%%", wzPackageId, dwProgressPercentage, dwOverallProgressPercentage); +#endif + + ::StringCchPrintfW(wzProgress, countof(wzProgress), L"%u%%", dwOverallProgressPercentage); + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_TEXT, wzProgress); + ThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_BAR, dwOverallProgressPercentage); + + BAL_INFO_PACKAGE* pPackage = NULL; + HRESULT hr = BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage); + LPCWSTR wzPackageName = (SUCCEEDED(hr) && pPackage->sczDisplayName) ? pPackage->sczDisplayName : wzPackageId; + + WCHAR wzInfo[1024] = { }; + if (m_fIsUninstall) + ::StringCchPrintfW(wzInfo, countof(wzInfo), L"Uninstalling %s ... [ %u%% ]", wzPackageName, dwProgressPercentage); + else + ::StringCchPrintfW(wzInfo, countof(wzInfo), L"Installing %s ... [ %u%% ]", wzPackageName, dwProgressPercentage); + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, wzInfo); + + m_dwCalculatedExecuteProgress = dwOverallProgressPercentage * (100 - WIXSTDBA_ACQUIRE_PERCENTAGE) / 100; +#ifdef DEBUG + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: OnExecuteProgress() - calculated progress: %u%%, displayed progress: %u%%", m_dwCalculatedExecuteProgress, m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress); +#endif + ThemeSetProgressControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_CALCULATED_PROGRESS_BAR, m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress); + + SetTaskbarButtonProgress(m_dwCalculatedCacheProgress + m_dwCalculatedExecuteProgress); + + return __super::OnExecuteProgress(wzPackageId, dwProgressPercentage, dwOverallProgressPercentage); + } + + + virtual STDMETHODIMP_(int) OnExecutePackageComplete( + __in_z LPCWSTR wzPackageId, + __in HRESULT hrExitCode, + __in BOOTSTRAPPER_APPLY_RESTART restart, + __in int nRecommendation + ) + { + SetProgressState(hrExitCode); + + int nResult = __super::OnExecutePackageComplete(wzPackageId, hrExitCode, restart, nRecommendation); + + if (m_sczPrereqPackage && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzPackageId, -1, m_sczPrereqPackage, -1)) + { + m_fPrereqInstalled = SUCCEEDED(hrExitCode); + + // If the pre-req required a restart (any restart) then do an immediate + // restart to ensure that the bundle will get launched again post reboot. + if (BOOTSTRAPPER_APPLY_RESTART_NONE != restart) + { + nResult = IDRESTART; + } + } + + + /// On package install complete, if WIXSTDBA_VARIABLE_LOGSPATH is defined + /// then will move the package installation log to the specified path. + if (BalStringVariableExists(WIXSTDBA_VARIABLE_LOGSPATH)) + { + LPWSTR wzVarPackageLog = NULL; + StrAllocFormatted(&wzVarPackageLog, L"WixBundleLog_%s", wzPackageId); + if (BalStringVariableExists(wzVarPackageLog)) + { + LPWSTR wzPackageLog = NULL; + LPWSTR wzInstallLogPath = NULL; + LPWSTR wzDstPackageLog = NULL; + + if ( SUCCEEDED(BalGetStringVariable(WIXSTDBA_VARIABLE_LOGSPATH, &wzInstallLogPath)) && + SUCCEEDED(BalGetStringVariable(wzVarPackageLog, &wzPackageLog))) + { + StrAllocFormatted(&wzDstPackageLog, L"%s\\%s", wzInstallLogPath, PathFile(wzPackageLog)); + DirEnsureExists(wzInstallLogPath, NULL); + FileEnsureMove(wzPackageLog, wzDstPackageLog, TRUE, TRUE); + } else + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Setup was unable to copy logs to the specified installation log path."); + + } + } + + return nResult; + } + + + virtual STDMETHODIMP_(void) OnExecuteComplete( + __in HRESULT hrStatus + ) + { + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_PACKAGE_TEXT, L""); + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_EXECUTE_PROGRESS_ACTIONDATA_TEXT, L""); + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_OVERALL_PROGRESS_PACKAGE_TEXT, L""); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, FALSE); // no more cancel. + + SetState(WIXSTDBA_STATE_EXECUTED, S_OK); // we always return success here and let OnApplyComplete() deal with the error. + SetProgressState(hrStatus); + } + + /* + virtual STDMETHODIMP_(int) OnResolveSource( + __in_z LPCWSTR wzPackageOrContainerId, + __in_z_opt LPCWSTR wzPayloadId, + __in_z LPCWSTR wzLocalSource, + __in_z_opt LPCWSTR wzDownloadSource + ) + { + int nResult = IDERROR; // assume we won't resolve source and that is unexpected. + + LPWSTR sczHTTPDwnUserName = NULL; + LPWSTR sczHTTPDwnPassword = NULL; + LPWSTR sczHTTPDwnHost = NULL; + BOOL bUseHTTPAuth = FALSE; + BOOL bUpdateDwnSrc = FALSE; + + + + if (BOOTSTRAPPER_DISPLAY_FULL == m_command.display) + { + if (wzDownloadSource) + { + if (bUseHTTPAuth || bUpdateDwnSrc) + { + HRESULT hr = m_pEngine->SetDownloadSource(wzPackageOrContainerId, wzPayloadId, wzDownloadSource, sczHTTPDwnUserName, sczHTTPDwnPassword); + nResult = SUCCEEDED(hr) ? IDDOWNLOAD : IDERROR; + } + else + nResult = IDDOWNLOAD; + } + else // prompt to change the source location. + { + OPENFILENAMEW ofn = { }; + WCHAR wzFile[MAX_PATH] = { }; + + ::StringCchCopyW(wzFile, countof(wzFile), wzLocalSource); + + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = m_hWnd; + ofn.lpstrFile = wzFile; + ofn.nMaxFile = countof(wzFile); + ofn.lpstrFilter = L"All Files\0*.*\0"; + ofn.nFilterIndex = 1; + ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; + ofn.lpstrTitle = m_pTheme->sczCaption; + + if (::GetOpenFileNameW(&ofn)) + { + HRESULT hr = m_pEngine->SetLocalSource(wzPackageOrContainerId, wzPayloadId, ofn.lpstrFile); + nResult = SUCCEEDED(hr) ? IDRETRY : IDERROR; + } + else + { + nResult = IDCANCEL; + } + } + } + else if (wzDownloadSource) + { + // If doing a non-interactive install and download source is available, let's try downloading the package silently + if (bUseHTTPAuth || bUpdateDwnSrc) + { + HRESULT hr = m_pEngine->SetDownloadSource(wzPackageOrContainerId, wzPayloadId, wzDownloadSource, sczHTTPDwnUserName, sczHTTPDwnPassword); + nResult = SUCCEEDED(hr) ? IDRETRY : IDERROR; + } + else + nResult = IDDOWNLOAD; + } + // else there's nothing more we can do in non-interactive mode + + return CheckCanceled() ? IDCANCEL : nResult; + } + */ + + virtual STDMETHODIMP_(int) OnResolveSource( + __in_z LPCWSTR wzPackageOrContainerId, + __in_z_opt LPCWSTR wzPayloadId, + __in_z LPCWSTR wzLocalSource, + __in_z_opt LPCWSTR wzDownloadSource + ) + { + int nResult = IDERROR; // assume we won't resolve source and that is unexpected. + + if (BOOTSTRAPPER_DISPLAY_FULL == m_command.display) + { + if (wzDownloadSource) + { + nResult = IDDOWNLOAD; + } + else // prompt to change the source location. + { + OPENFILENAMEW ofn = { }; + WCHAR wzFile[MAX_PATH] = { }; + + ::StringCchCopyW(wzFile, countof(wzFile), wzLocalSource); + + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = m_hWnd; + ofn.lpstrFile = wzFile; + ofn.nMaxFile = countof(wzFile); + ofn.lpstrFilter = L"All Files\0*.*\0"; + ofn.nFilterIndex = 1; + ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; + ofn.lpstrTitle = m_pTheme->sczCaption; + + if (::GetOpenFileNameW(&ofn)) + { + HRESULT hr = m_pEngine->SetLocalSource(wzPackageOrContainerId, wzPayloadId, ofn.lpstrFile); + nResult = SUCCEEDED(hr) ? IDRETRY : IDERROR; + } + else + { + nResult = IDCANCEL; + } + } + } + else if (wzDownloadSource) + { + // If doing a non-interactive install and download source is available, let's try downloading the package silently + nResult = IDDOWNLOAD; + } + // else there's nothing more we can do in non-interactive mode + + return CheckCanceled() ? IDCANCEL : nResult; + } + + + virtual STDMETHODIMP_(int) OnApplyComplete( + __in HRESULT hrStatus, + __in BOOTSTRAPPER_APPLY_RESTART restart + ) + { + m_restartResult = restart; // remember the restart result so we return the correct error code no matter what the user chooses to do in the UI. + + // If a restart was encountered and we are not suppressing restarts, then restart is required. + m_fRestartRequired = (BOOTSTRAPPER_APPLY_RESTART_NONE != restart && BOOTSTRAPPER_RESTART_NEVER < m_command.restart); + // If a restart is required and we're not displaying a UI or we are not supposed to prompt for restart then allow the restart. + m_fAllowRestart = m_fRestartRequired && (BOOTSTRAPPER_DISPLAY_FULL > m_command.display || BOOTSTRAPPER_RESTART_PROMPT < m_command.restart); + + // If we are showing UI, wait a beat before moving to the final screen. + if (BOOTSTRAPPER_DISPLAY_NONE < m_command.display) + { + ::Sleep(250); + } + + SetState(WIXSTDBA_STATE_APPLIED, hrStatus); + SetTaskbarButtonProgress(100); // show full progress bar, green, yellow, or red + + // If we successfully applied an update close the window since the new Bundle should be running now. + if (SUCCEEDED(hrStatus) && m_fUpdating) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Update downloaded, close bundle."); + ::PostMessageW(m_hWnd, WM_CLOSE, 0, 0); + } + + return IDNOACTION; + } + + +private: // privates + // + // UiThreadProc - entrypoint for UI thread. + // + static DWORD WINAPI UiThreadProc( + __in LPVOID pvContext + ) + { + HRESULT hr = S_OK; + CWixStandardBootstrapperApplication* pThis = (CWixStandardBootstrapperApplication*)pvContext; + BOOL fComInitialized = FALSE; + BOOL fRet = FALSE; + MSG msg = { }; + + // Initialize COM and theme. + hr = ::CoInitialize(NULL); + BalExitOnFailure(hr, "Failed to initialize COM."); + fComInitialized = TRUE; + + hr = ThemeInitialize(pThis->m_hModule); + BalExitOnFailure(hr, "Failed to initialize theme manager."); + + hr = pThis->InitializeData(); + BalExitOnFailure(hr, "Failed to initialize data in bootstrapper application."); + + // Create main window. + pThis->InitializeTaskbarButton(); + hr = pThis->CreateMainWindow(); + BalExitOnFailure(hr, "Failed to create main window."); + + // Okay, we're ready for packages now. + pThis->SetState(WIXSTDBA_STATE_INITIALIZED, hr); + ::PostMessageW(pThis->m_hWnd, BOOTSTRAPPER_ACTION_HELP == pThis->m_command.action ? WM_WIXSTDBA_SHOW_HELP : WM_WIXSTDBA_DETECT_PACKAGES, 0, 0); + + // message pump + while (0 != (fRet = ::GetMessageW(&msg, NULL, 0, 0))) + { + if (-1 == fRet) + { + hr = E_UNEXPECTED; + BalExitOnFailure(hr, "Unexpected return value from message pump."); + } + else if (!ThemeHandleKeyboardMessage(pThis->m_pTheme, msg.hwnd, &msg)) + { + ::TranslateMessage(&msg); + ::DispatchMessageW(&msg); + } + } + + // Succeeded thus far, check to see if anything went wrong while actually + // executing changes. + if (FAILED(pThis->m_hrFinal)) + { + hr = pThis->m_hrFinal; + } + else if (pThis->CheckCanceled()) + { + hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT); + } + +LExit: + // destroy main window + pThis->DestroyMainWindow(); + + // initiate engine shutdown + DWORD dwQuit = HRESULT_CODE(hr); + if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == pThis->m_restartResult) + { + dwQuit = ERROR_SUCCESS_REBOOT_INITIATED; + } + else if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == pThis->m_restartResult) + { + dwQuit = ERROR_SUCCESS_REBOOT_REQUIRED; + } + pThis->m_pEngine->Quit(dwQuit); + + ReleaseTheme(pThis->m_pTheme); + ThemeUninitialize(); + + // uninitialize COM + if (fComInitialized) + { + ::CoUninitialize(); + } + + return hr; + } + + + static DWORD WINAPI ThreadProc( + __in LPVOID pvContext + ) + { + CWixStandardBootstrapperApplication* pThis = static_cast(pvContext);; + + HRESULT hr = S_OK; + IXMLDOMDocument *pixd = NULL; + IXMLDOMNode* pNode = NULL; + LPWSTR sczUpdateUrl = NULL; + DWORD64 qwSize = 0; + + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Checking for update."); + + // Load the update XML from a location url and parse it for an update. + // + // + // + // + // + + hr = XmlLoadDocumentFromFile(pThis->m_wzUpdateLocation, &pixd); + BalExitOnFailure(hr, "Failed to load version check XML document."); + + hr = XmlSelectSingleNode(pixd, L"/Setup/Upgrade", &pNode); + BalExitOnFailure(hr, "Failed to select upgrade node."); + + if (S_OK == hr) + { + hr = XmlGetAttributeEx(pNode, L"Url", &sczUpdateUrl); + BalExitOnFailure(hr, "Failed to get url attribute."); + + hr = XmlGetAttributeLargeNumber(pNode, L"Size", &qwSize); + } + + if (sczUpdateUrl && *sczUpdateUrl) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Update available, url: %ls; size: %I64u.", sczUpdateUrl, qwSize); + // Show upgrade on install and modify pages + if (pThis->m_rgdwPageIds[WIXSTDBA_PAGE_INSTALL] == pThis->m_dwCurrentPage || + pThis->m_rgdwPageIds[WIXSTDBA_PAGE_MODIFY] == pThis->m_dwCurrentPage) + { + pThis->m_pEngine->SetUpdate(NULL, sczUpdateUrl, qwSize, BOOTSTRAPPER_UPDATE_HASH_TYPE_NONE, NULL, 0); + ThemeControlEnable(pThis->m_pTheme, WIXSTDBA_CONTROL_UPGRADE_LINK, TRUE); + } + } + else + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "No update available."); + } + +LExit: + ReleaseObject(pixd); + ReleaseObject(pNode); + ReleaseStr(sczUpdateUrl); + + return 0; + } + + + // + // InitializeData - initializes all the package and prereq information. + // + HRESULT InitializeData() + { + HRESULT hr = S_OK; + LPWSTR sczModulePath = NULL; + IXMLDOMDocument *pixdManifest = NULL; + + hr = BalManifestLoad(m_hModule, &pixdManifest); + BalExitOnFailure(hr, "Failed to load bootstrapper application manifest."); + + hr = ParseOverridableVariablesFromXml(pixdManifest); + BalExitOnFailure(hr, "Failed to read overridable variables."); + + hr = ProcessCommandLine(&m_sczLanguage); + ExitOnFailure(hr, "Unknown commandline parameters."); + + // Override default language to correctly support UK English (this is not required in WiX 3.8) + if (!(m_sczLanguage && *m_sczLanguage)) + { + hr = StrAllocFormatted(&m_sczLanguage, L"%u", ::GetUserDefaultLangID()); + BalExitOnFailure(hr, "Failed to set language."); + } + + hr = PathRelativeToModule(&sczModulePath, NULL, m_hModule); + BalExitOnFailure(hr, "Failed to get module path."); + + hr = LoadLocalization(sczModulePath, m_sczLanguage); + ExitOnFailure(hr, "Failed to load localization."); + + hr = LoadTheme(sczModulePath, m_sczLanguage); + ExitOnFailure(hr, "Failed to load theme."); + + hr = BalInfoParseFromXml(&m_Bundle, pixdManifest); + BalExitOnFailure(hr, "Failed to load bundle information."); + + hr = BalConditionsParseFromXml(&m_Conditions, pixdManifest, m_pWixLoc); + BalExitOnFailure(hr, "Failed to load conditions from XML."); + + LoadBootstrapperBAFunctions(); + + hr = ParseBootrapperApplicationDataFromXml(pixdManifest); + BalExitOnFailure(hr, "Failed to read bootstrapper application data."); + + LOC_STRING* pLocString = NULL; + LocGetString(m_pWixLoc, L"#(loc.ProgressHeader)", &pLocString); + m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_PROGRESS_HEADER, pLocString->wzText); + LocGetString(m_pWixLoc, L"#(loc.ProgressInfo)", &pLocString); + m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_PROGRESS_INFO, pLocString->wzText); + LocGetString(m_pWixLoc, L"#(loc.SuccessHeader)", &pLocString); + m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_SUCCESS_HEADER, pLocString->wzText); + LocGetString(m_pWixLoc, L"#(loc.SuccessInfo)", &pLocString); + m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_SUCCESS_INFO, pLocString->wzText); + LocGetString(m_pWixLoc, L"#(loc.FailureHeader)", &pLocString); + m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_FAILURE_HEADER, pLocString->wzText); + if (m_fPrereq) + { + hr = ParsePrerequisiteInformationFromXml(pixdManifest); + BalExitOnFailure(hr, "Failed to read prerequisite information."); + } + else + { + hr = ParseBootrapperApplicationDataFromXml(pixdManifest); + BalExitOnFailure(hr, "Failed to read bootstrapper application data."); + } + + +LExit: + ReleaseObject(pixdManifest); + ReleaseStr(sczModulePath); + + return hr; + } + + + // + // ProcessCommandLine - process the provided command line arguments. + // + HRESULT ProcessCommandLine( + __inout LPWSTR* psczLanguage + ) + { + HRESULT hr = S_OK; + int argc = 0; + LPWSTR* argv = NULL; + LPWSTR sczVariableName = NULL; + LPWSTR sczVariableValue = NULL; + + if (m_command.wzCommandLine && *m_command.wzCommandLine) + { + argv = ::CommandLineToArgvW(m_command.wzCommandLine, &argc); + ExitOnNullWithLastError(argv, hr, "Failed to get command line."); + + for (int i = 0; i < argc; ++i) + { + if (argv[i][0] == L'-' || argv[i][0] == L'/') + { + if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"lang", -1)) + { + if (i + 1 >= argc) + { + hr = E_INVALIDARG; + BalExitOnFailure(hr, "Must specify a language."); + } + + ++i; + + hr = StrAllocString(psczLanguage, &argv[i][0], 0); + BalExitOnFailure(hr, "Failed to copy language."); + } + } + else if (m_sdOverridableVariables) + { + const wchar_t* pwc = wcschr(argv[i], L'='); + if (pwc) + { + hr = StrAllocString(&sczVariableName, argv[i], pwc - argv[i]); + BalExitOnFailure(hr, "Failed to copy variable name."); + + hr = DictKeyExists(m_sdOverridableVariables, sczVariableName); + if (E_NOTFOUND == hr) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Ignoring attempt to set non-overridable variable: '%ls'.", sczVariableName); + hr = S_OK; + continue; + } + ExitOnFailure(hr, "Failed to check the dictionary of overridable variables."); + + hr = StrAllocString(&sczVariableValue, ++pwc, 0); + BalExitOnFailure(hr, "Failed to copy variable value."); + + hr = m_pEngine->SetVariableString(sczVariableName, sczVariableValue); + BalExitOnFailure(hr, "Failed to set variable."); + } + else + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Ignoring unknown argument: %ls", argv[i]); + } + } + } + } + +LExit: + if (argv) + { + ::LocalFree(argv); + } + + ReleaseStr(sczVariableName); + ReleaseStr(sczVariableValue); + + return hr; + } + + HRESULT LoadLocalization( + __in_z LPCWSTR wzModulePath, + __in_z_opt LPCWSTR wzLanguage + ) + { + HRESULT hr = S_OK; + LPWSTR sczLocPath = NULL; + LPCWSTR wzLocFileName = L"thm.wxl"; + + hr = LocProbeForFile(wzModulePath, wzLocFileName, wzLanguage, &sczLocPath); + BalExitOnFailure2(hr, "Failed to probe for loc file: %ls in path: %ls", wzLocFileName, wzModulePath); + + hr = LocLoadFromFile(sczLocPath, &m_pWixLoc); + BalExitOnFailure1(hr, "Failed to load loc file from path: %ls", sczLocPath); + + if (WIX_LOCALIZATION_LANGUAGE_NOT_SET != m_pWixLoc->dwLangId) + { + ::SetThreadLocale(m_pWixLoc->dwLangId); + } + + hr = StrAllocString(&m_sczConfirmCloseMessage, L"#(loc.ConfirmCancelMessage)", 0); + ExitOnFailure(hr, "Failed to initialize confirm message loc identifier."); + + hr = LocLocalizeString(m_pWixLoc, &m_sczConfirmCloseMessage); + BalExitOnFailure1(hr, "Failed to localize confirm close message: %ls", m_sczConfirmCloseMessage); + +LExit: + ReleaseStr(sczLocPath); + + return hr; + } + + + HRESULT LoadTheme( + __in_z LPCWSTR wzModulePath, + __in_z_opt LPCWSTR wzLanguage + ) + { + HRESULT hr = S_OK; + LPWSTR sczThemePath = NULL; + LPCWSTR wzThemeFileName = L"thm.xml"; + LPWSTR sczCaption = NULL; + + hr = LocProbeForFile(wzModulePath, wzThemeFileName, wzLanguage, &sczThemePath); + BalExitOnFailure2(hr, "Failed to probe for theme file: %ls in path: %ls", wzThemeFileName, wzModulePath); + + hr = ThemeLoadFromFile(sczThemePath, &m_pTheme); + BalExitOnFailure1(hr, "Failed to load theme from path: %ls", sczThemePath); + + hr = ThemeLocalize(m_pTheme, m_pWixLoc); + BalExitOnFailure1(hr, "Failed to localize theme: %ls", sczThemePath); + + // Update the caption if there are any formatted strings in it. + hr = BalFormatString(m_pTheme->sczCaption, &sczCaption); + if (SUCCEEDED(hr)) + { + ThemeUpdateCaption(m_pTheme, sczCaption); + } + +LExit: + ReleaseStr(sczCaption); + ReleaseStr(sczThemePath); + + return hr; + } + + + HRESULT ParseOverridableVariablesFromXml( + __in IXMLDOMDocument* pixdManifest + ) + { + HRESULT hr = S_OK; + IXMLDOMNode* pNode = NULL; + IXMLDOMNodeList* pNodes = NULL; + DWORD cNodes = 0; + LPWSTR scz = NULL; + + // get the list of variables users can override on the command line + hr = XmlSelectNodes(pixdManifest, L"/BootstrapperApplicationData/WixStdbaOverridableVariable", &pNodes); + if (S_FALSE == hr) + { + ExitFunction1(hr = S_OK); + } + ExitOnFailure(hr, "Failed to select overridable variable nodes."); + + hr = pNodes->get_length((long*)&cNodes); + ExitOnFailure(hr, "Failed to get overridable variable node count."); + + if (cNodes) + { + hr = DictCreateStringList(&m_sdOverridableVariables, 32, DICT_FLAG_NONE); + ExitOnFailure(hr, "Failed to create the string dictionary."); + + for (DWORD i = 0; i < cNodes; ++i) + { + hr = XmlNextElement(pNodes, &pNode, NULL); + ExitOnFailure(hr, "Failed to get next node."); + + // @Name + hr = XmlGetAttributeEx(pNode, L"Name", &scz); + ExitOnFailure(hr, "Failed to get @Name."); + + hr = DictAddKey(m_sdOverridableVariables, scz); + ExitOnFailure1(hr, "Failed to add \"%ls\" to the string dictionary.", scz); + + // prepare next iteration + ReleaseNullObject(pNode); + } + } + +LExit: + ReleaseObject(pNode); + ReleaseObject(pNodes); + ReleaseStr(scz); + return hr; + } + + + HRESULT ParsePrerequisiteInformationFromXml( + __in IXMLDOMDocument* pixdManifest + ) + { + HRESULT hr = S_OK; + IXMLDOMNode* pNode = NULL; + + hr = XmlSelectSingleNode(pixdManifest, L"/BootstrapperApplicationData/WixMbaPrereqInformation", &pNode); + if (S_FALSE == hr) + { + hr = E_INVALIDARG; + } + BalExitOnFailure(hr, "BootstrapperApplication.xml manifest is missing prerequisite information."); + + hr = XmlGetAttributeEx(pNode, L"PackageId", &m_sczPrereqPackage); + BalExitOnFailure(hr, "Failed to get prerequisite package identifier."); + + hr = XmlGetAttributeEx(pNode, L"LicenseUrl", &m_sczLicenseUrl); + if (E_NOTFOUND == hr) + { + hr = S_OK; + } + BalExitOnFailure(hr, "Failed to get prerequisite license URL."); + + hr = XmlGetAttributeEx(pNode, L"LicenseFile", &m_sczLicenseFile); + if (E_NOTFOUND == hr) + { + hr = S_OK; + } + BalExitOnFailure(hr, "Failed to get prerequisite license file."); + +LExit: + ReleaseObject(pNode); + return hr; + } + + + HRESULT ParseBootrapperApplicationDataFromXml( + __in IXMLDOMDocument* pixdManifest + ) + { + HRESULT hr = S_OK; + IXMLDOMNode* pNode = NULL; + DWORD dwBool = 0; + + hr = XmlSelectSingleNode(pixdManifest, L"/BootstrapperApplicationData/WixExtbaInformation", &pNode); + if (S_FALSE == hr) + { + hr = E_INVALIDARG; + } + BalExitOnFailure(hr, "BootstrapperApplication.xml manifest is missing wixextba information."); + + hr = XmlGetAttributeEx(pNode, L"LicenseFile", &m_sczLicenseFile); + if (E_NOTFOUND == hr) + { + hr = S_OK; + } + BalExitOnFailure(hr, "Failed to get license file."); + + hr = XmlGetAttributeEx(pNode, L"LicenseUrl", &m_sczLicenseUrl); + if (E_NOTFOUND == hr) + { + hr = S_OK; + } + BalExitOnFailure(hr, "Failed to get license URL."); + + ReleaseObject(pNode); + + hr = XmlSelectSingleNode(pixdManifest, L"/BootstrapperApplicationData/WixExtbaOptions", &pNode); + if (S_FALSE == hr) + { + ExitFunction1(hr = S_OK); + } + BalExitOnFailure(hr, "Failed to read wixextba options from BootstrapperApplication.xml manifest."); + + hr = XmlGetAttributeNumber(pNode, L"SuppressOptionsUI", &dwBool); + if (E_NOTFOUND == hr) + { + hr = S_OK; + } + else if (SUCCEEDED(hr)) + { + m_fSuppressOptionsUI = 0 < dwBool; + } + BalExitOnFailure(hr, "Failed to get SuppressOptionsUI value."); + + dwBool = 0; + hr = XmlGetAttributeNumber(pNode, L"SuppressDowngradeFailure", &dwBool); + if (E_NOTFOUND == hr) + { + hr = S_OK; + } + else if (SUCCEEDED(hr)) + { + m_fSuppressDowngradeFailure = 0 < dwBool; + } + BalExitOnFailure(hr, "Failed to get SuppressDowngradeFailure value."); + + dwBool = 0; + hr = XmlGetAttributeNumber(pNode, L"SuppressRepair", &dwBool); + if (E_NOTFOUND == hr) + { + hr = S_OK; + } + else if (SUCCEEDED(hr)) + { + m_fSuppressRepair = 0 < dwBool; + } + BalExitOnFailure(hr, "Failed to get SuppressRepair value."); + + hr = XmlGetAttributeNumber(pNode, L"ShowVersion", &dwBool); + if (E_NOTFOUND == hr) + { + hr = S_OK; + } + else if (SUCCEEDED(hr)) + { + m_fShowVersion = 0 < dwBool; + } + BalExitOnFailure(hr, "Failed to get ShowVersion value."); + +LExit: + ReleaseObject(pNode); + return hr; + } + + + // + // CreateMainWindow - creates the main install window. + // + HRESULT CreateMainWindow() + { + HRESULT hr = S_OK; + HICON hIcon = reinterpret_cast(m_pTheme->hIcon); + WNDCLASSW wc = { }; + DWORD dwWindowStyle = 0; + int x = CW_USEDEFAULT; + int y = CW_USEDEFAULT; + POINT ptCursor = { }; + HMONITOR hMonitor = NULL; + MONITORINFO mi = { }; + + // If the theme did not provide an icon, try using the icon from the bundle engine. + if (!hIcon) + { + HMODULE hBootstrapperEngine = ::GetModuleHandleW(NULL); + if (hBootstrapperEngine) + { + hIcon = ::LoadIconW(hBootstrapperEngine, MAKEINTRESOURCEW(1)); + } + } + + // Register the window class and create the window. + wc.lpfnWndProc = CWixStandardBootstrapperApplication::WndProc; + wc.hInstance = m_hModule; + wc.hIcon = hIcon; + wc.hCursor = ::LoadCursorW(NULL, (LPCWSTR)IDC_ARROW); + wc.hbrBackground = m_pTheme->rgFonts[m_pTheme->dwFontId].hBackground; + wc.lpszMenuName = NULL; + wc.lpszClassName = WIXSTDBA_WINDOW_CLASS; + if (!::RegisterClassW(&wc)) + { + ExitWithLastError(hr, "Failed to register window."); + } + + m_fRegistered = TRUE; + + // Calculate the window style based on the theme style and command display value. + dwWindowStyle = m_pTheme->dwStyle; + if (BOOTSTRAPPER_DISPLAY_NONE >= m_command.display) + { + dwWindowStyle &= ~WS_VISIBLE; + } + + // Don't show the window if there is a splash screen (it will be made visible when the splash screen is hidden) + if (::IsWindow(m_command.hwndSplashScreen)) + { + dwWindowStyle &= ~WS_VISIBLE; + } + + // Center the window on the monitor with the mouse. + if (::GetCursorPos(&ptCursor)) + { + hMonitor = ::MonitorFromPoint(ptCursor, MONITOR_DEFAULTTONEAREST); + if (hMonitor) + { + mi.cbSize = sizeof(mi); + if (::GetMonitorInfoW(hMonitor, &mi)) + { + x = mi.rcWork.left + (mi.rcWork.right - mi.rcWork.left - m_pTheme->nWidth) / 2; + y = mi.rcWork.top + (mi.rcWork.bottom - mi.rcWork.top - m_pTheme->nHeight) / 2; + } + } + } + + m_hWnd = ::CreateWindowExW(0, wc.lpszClassName, m_pTheme->sczCaption, dwWindowStyle, x, y, m_pTheme->nWidth, m_pTheme->nHeight, HWND_DESKTOP, NULL, m_hModule, this); + ExitOnNullWithLastError(m_hWnd, hr, "Failed to create window."); + + hr = S_OK; + +LExit: + return hr; + } + + + // + // InitializeTaskbarButton - initializes taskbar button for progress. + // + void InitializeTaskbarButton() + { + HRESULT hr = S_OK; + + hr = ::CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_ALL, __uuidof(ITaskbarList3), reinterpret_cast(&m_pTaskbarList)); + if (REGDB_E_CLASSNOTREG == hr) // not supported before Windows 7 + { + ExitFunction1(hr = S_OK); + } + BalExitOnFailure(hr, "Failed to create ITaskbarList3. Continuing."); + + m_uTaskbarButtonCreatedMessage = ::RegisterWindowMessageW(L"TaskbarButtonCreated"); + BalExitOnNullWithLastError(m_uTaskbarButtonCreatedMessage, hr, "Failed to get TaskbarButtonCreated message. Continuing."); + +LExit: + return; + } + + // + // DestroyMainWindow - clean up all the window registration. + // + void DestroyMainWindow() + { + if (::IsWindow(m_hWnd)) + { + ::DestroyWindow(m_hWnd); + m_hWnd = NULL; + m_fTaskbarButtonOK = FALSE; + } + + if (m_fRegistered) + { + ::UnregisterClassW(WIXSTDBA_WINDOW_CLASS, m_hModule); + m_fRegistered = FALSE; + } + } + + + // + // WndProc - standard windows message handler. + // + static LRESULT CALLBACK WndProc( + __in HWND hWnd, + __in UINT uMsg, + __in WPARAM wParam, + __in LPARAM lParam + ) + { +#pragma warning(suppress:4312) + CWixStandardBootstrapperApplication* pBA = reinterpret_cast(::GetWindowLongPtrW(hWnd, GWLP_USERDATA)); + + switch (uMsg) + { + case WM_NCCREATE: + { + LPCREATESTRUCT lpcs = reinterpret_cast(lParam); + pBA = reinterpret_cast(lpcs->lpCreateParams); +#pragma warning(suppress:4244) + ::SetWindowLongPtrW(hWnd, GWLP_USERDATA, reinterpret_cast(pBA)); + } + break; + + case WM_NCDESTROY: + { + LRESULT lres = ThemeDefWindowProc(pBA ? pBA->m_pTheme : NULL, hWnd, uMsg, wParam, lParam); + ::SetWindowLongPtrW(hWnd, GWLP_USERDATA, 0); + return lres; + } + + case WM_CREATE: + if (!pBA->OnCreate(hWnd)) + { + return -1; + } + break; + + case WM_QUERYENDSESSION: + return IDCANCEL != pBA->OnSystemShutdown(static_cast(lParam), IDCANCEL); + + case WM_CLOSE: + // If the user chose not to close, do *not* let the default window proc handle the message. + if (!pBA->OnClose()) + { + return 0; + } + break; + + case WM_DESTROY: + ::PostQuitMessage(0); + break; + + case WM_WIXSTDBA_SHOW_HELP: + pBA->OnShowHelp(); + return 0; + + case WM_WIXSTDBA_DETECT_PACKAGES: + pBA->OnDetect(); + return 0; + + case WM_WIXSTDBA_PLAN_PACKAGES: + pBA->OnPlan(static_cast(lParam)); + return 0; + + case WM_WIXSTDBA_APPLY_PACKAGES: + pBA->OnApply(); + return 0; + + case WM_WIXSTDBA_CHANGE_STATE: + pBA->OnChangeState(static_cast(lParam)); + return 0; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX: + pBA->OnClickAcceptCheckbox(); + return 0; + + case WIXSTDBA_CONTROL_PERMACHINE_RADIO: __fallthrough; + case WIXSTDBA_CONTROL_PERUSER_RADIO: + pBA->OnClickInstallScope(); + return 0; + + case WIXSTDBA_CONTROL_REGSIGNIN_RADIO: __fallthrough; + case WIXSTDBA_CONTROL_REGCREATE_RADIO: __fallthrough; + case WIXSTDBA_CONTROL_SKIPREG_CHECKBOX: + pBA->OnClickSkipRegistrationCheckbox(); + return 0; + + + case WIXSTDBA_CONTROL_OPTIONS_BUTTON: + pBA->OnClickOptionsButton(); + return 0; + + case WIXSTDBA_CONTROL_BROWSE_BUTTON: + pBA->OnClickOptionsBrowseButton(WIXSTDBA_CONTROL_BROWSE_BUTTON); + return 0; + + case WIXSTDBA_CONTROL_OK_BUTTON: + pBA->OnClickOptionsOkButton(); + return 0; + + case WIXSTDBA_CONTROL_CANCEL_BUTTON: + pBA->OnClickOptionsCancelButton(); + return 0; + + case WIXSTDBA_CONTROL_INSTALL_BUTTON: + pBA->OnClickInstallButton(); + return 0; + + case WIXSTDBA_CONTROL_REPAIR_BUTTON: + pBA->OnClickRepairButton(); + return 0; + + case WIXSTDBA_CONTROL_UNINSTALL_BUTTON: + pBA->OnClickUninstallButton(); + return 0; + + case WIXSTDBA_CONTROL_LAUNCH_BUTTON: + pBA->OnClickLaunchButton(); + return 0; + + case WIXSTDBA_CONTROL_SUCCESS_RESTART_BUTTON: __fallthrough; + case WIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON: + pBA->OnClickRestartButton(); + return 0; + + case WIXSTDBA_CONTROL_HELP_CANCEL_BUTTON: __fallthrough; + + case WIXSTDBA_CONTROL_WELCOME_CANCEL_BUTTON: __fallthrough; + case WIXSTDBA_CONTROL_MODIFY_CANCEL_BUTTON: __fallthrough; + case WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON: __fallthrough; + case WIXSTDBA_CONTROL_SUCCESS_CANCEL_BUTTON: __fallthrough; + case WIXSTDBA_CONTROL_FAILURE_CANCEL_BUTTON: __fallthrough; + case WIXSTDBA_CONTROL_CLOSE_BUTTON: + pBA->OnClickCloseButton(); + return 0; + case WIXSTDBA_CONTROL_NEXT_BUTTON: + pBA->OnClickNextButton(); + return 0; + case WIXSTDBA_CONTROL_BACK_BUTTON: + pBA->OnClickBackButton(); + return 0; + + } + break; + + case WM_NOTIFY: + if (lParam) + { + LPNMHDR pnmhdr = reinterpret_cast(lParam); + switch (pnmhdr->code) + { + case NM_CLICK: __fallthrough; + case NM_RETURN: + switch (static_cast(pnmhdr->idFrom)) + { + case WIXSTDBA_CONTROL_EULA_LINK: + pBA->OnClickEulaLink(); + return 1; + case WIXSTDBA_CONTROL_FAILURE_LOGFILE_LINK: + pBA->OnClickLogFileLink(); + return 1; + case WIXSTDBA_CONTROL_UPGRADE_LINK: + pBA->OnClickUpgradeLink(); + return 1; + } + } + } + break; + } + + if (pBA && pBA->m_pTaskbarList && uMsg == pBA->m_uTaskbarButtonCreatedMessage) + { + pBA->m_fTaskbarButtonOK = TRUE; + return 0; + } + + return ThemeDefWindowProc(pBA ? pBA->m_pTheme : NULL, hWnd, uMsg, wParam, lParam); + } + + + // + // OnCreate - finishes loading the theme. + // + BOOL OnCreate( + __in HWND hWnd + ) + { + HRESULT hr = S_OK; + LPWSTR sczText = NULL; + LPWSTR sczLicenseFormatted = NULL; + LPWSTR sczLicensePath = NULL; + LPWSTR sczLicenseDirectory = NULL; + LPWSTR sczLicenseFilename = NULL; + + hr = ThemeLoadControls(m_pTheme, hWnd, vrgInitControls, countof(vrgInitControls)); + BalExitOnFailure(hr, "Failed to load theme controls."); + + C_ASSERT(COUNT_WIXSTDBA_PAGE == countof(vrgwzPageNames)); + C_ASSERT(countof(m_rgdwPageIds) == countof(vrgwzPageNames)); + + ThemeGetPageIds(m_pTheme, vrgwzPageNames, m_rgdwPageIds, countof(m_rgdwPageIds)); + + // Initialize the text on all "application" (non-page) controls. + for (DWORD i = 0; i < m_pTheme->cControls; ++i) + { + THEME_CONTROL* pControl = m_pTheme->rgControls + i; + if (!pControl->wPageId && pControl->sczText && *pControl->sczText) + { + HRESULT hrFormat = BalFormatString(pControl->sczText, &sczText); + if (SUCCEEDED(hrFormat)) + { + ThemeSetTextControl(m_pTheme, pControl->wId, sczText); + } + } + } + + // Load the RTF EULA control with text if the control exists. + if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_EULA_RICHEDIT)) + { + hr = (m_sczLicenseFile && *m_sczLicenseFile) ? S_OK : E_INVALIDDATA; + if (SUCCEEDED(hr)) + { + hr = StrAllocString(&sczLicenseFormatted, m_sczLicenseFile, 0); + if (SUCCEEDED(hr)) + { + hr = LocLocalizeString(m_pWixLoc, &sczLicenseFormatted); + if (SUCCEEDED(hr)) + { + hr = BalFormatString(sczLicenseFormatted, &sczLicenseFormatted); + if (SUCCEEDED(hr)) + { + hr = PathRelativeToModule(&sczLicensePath, sczLicenseFormatted, m_hModule); + if (SUCCEEDED(hr)) + { + hr = PathGetDirectory(sczLicensePath, &sczLicenseDirectory); + if (SUCCEEDED(hr)) + { + hr = StrAllocString(&sczLicenseFilename, PathFile(sczLicenseFormatted), 0); + if (SUCCEEDED(hr)) + { + hr = LocProbeForFile(sczLicenseDirectory, sczLicenseFilename, m_sczLanguage, &sczLicensePath); + if (SUCCEEDED(hr)) + { + hr = ThemeLoadRichEditFromFile(m_pTheme, WIXSTDBA_CONTROL_EULA_RICHEDIT, sczLicensePath, m_hModule); + } + } + } + } + } + } + } + } + + if (FAILED(hr)) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Failed to load file into license richedit control from path '%ls' manifest value: %ls", sczLicensePath, m_sczLicenseFile); + hr = S_OK; + } + } + +LExit: + ReleaseStr(sczLicenseFilename); + ReleaseStr(sczLicenseDirectory); + ReleaseStr(sczLicensePath); + ReleaseStr(sczLicenseFormatted); + ReleaseStr(sczText); + + return SUCCEEDED(hr); + } + + + // + // OnShowHelp - display the help page. + // + void OnShowHelp() + { + SetState(WIXSTDBA_STATE_HELP, S_OK); + + // If the UI should be visible, display it now and hide the splash screen + if (BOOTSTRAPPER_DISPLAY_NONE < m_command.display) + { + ::ShowWindow(m_pTheme->hwndParent, SW_SHOW); + } + + m_pEngine->CloseSplashScreen(); + + return; + } + + + // + // OnDetect - start the processing of packages. + // + void OnDetect() + { + HRESULT hr = S_OK; + + if (m_pBAFunction) + { + hr = m_pBAFunction->OnDetect(); + BalExitOnFailure(hr, "Failed calling detect BA function."); + } + + SetState(WIXSTDBA_STATE_DETECTING, hr); + + // If the UI should be visible, display it now and hide the splash screen + if (BOOTSTRAPPER_DISPLAY_NONE < m_command.display) + { + ::ShowWindow(m_pTheme->hwndParent, SW_SHOW); + } + + m_pEngine->CloseSplashScreen(); + + // Tell the core we're ready for the packages to be processed now. + hr = m_pEngine->Detect(); + BalExitOnFailure(hr, "Failed to start detecting chain."); + +LExit: + if (FAILED(hr)) + { + SetState(WIXSTDBA_STATE_DETECTING, hr); + } + + return; + } + + + // + // OnPlan - plan the detected changes. + // + void OnPlan( + __in BOOTSTRAPPER_ACTION action + ) + { + HRESULT hr = S_OK; + + m_plannedAction = action; + + LOC_STRING* pLocString = NULL; + + if (m_plannedAction == BOOTSTRAPPER_ACTION_UNINSTALL) + { + m_fIsUninstall = TRUE; + LocGetString(m_pWixLoc, L"#(loc.ProgressHeaderUninstall)", &pLocString); + m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_PROGRESS_HEADER, pLocString->wzText); + LocGetString(m_pWixLoc, L"#(loc.ProgressInfoUninstall)", &pLocString); + m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_PROGRESS_INFO, pLocString->wzText); + } + + if (m_plannedAction == BOOTSTRAPPER_ACTION_REPAIR) + { + m_fIsRepair = TRUE; + LocGetString(m_pWixLoc, L"#(loc.ProgressHeaderRepair)", &pLocString); + m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_PROGRESS_HEADER, pLocString->wzText); + LocGetString(m_pWixLoc, L"#(loc.ProgressInfoRepair)", &pLocString); + m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_PROGRESS_INFO, pLocString->wzText); + } + + // If we are going to apply a downgrade, bail. + if (m_fDowngrading && BOOTSTRAPPER_ACTION_UNINSTALL < action) + { + if (m_fSuppressDowngradeFailure) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "A newer version of this product is installed but downgrade failure has been suppressed; continuing..."); + } + else + { + hr = HRESULT_FROM_WIN32(ERROR_PRODUCT_VERSION); + BalExitOnFailure(hr, "Cannot install a product when a newer version is installed."); + } + } + + SetState(WIXSTDBA_STATE_PLANNING, hr); + + if (m_pBAFunction) + { + m_pBAFunction->OnPlan(); + } + + hr = m_pEngine->Plan(action); + BalExitOnFailure(hr, "Failed to start planning packages."); + +LExit: + if (FAILED(hr)) + { + SetState(WIXSTDBA_STATE_PLANNING, hr); + } + + return; + } + + + // + // OnApply - apply the packages. + // + void OnApply() + { + HRESULT hr = S_OK; + + SetState(WIXSTDBA_STATE_APPLYING, hr); + SetProgressState(hr); + SetTaskbarButtonProgress(0); + + hr = m_pEngine->Apply(m_hWnd); + BalExitOnFailure(hr, "Failed to start applying packages."); + + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, TRUE); // ensure the cancel button is enabled before starting. + +LExit: + if (FAILED(hr)) + { + SetState(WIXSTDBA_STATE_APPLYING, hr); + } + + return; + } + + + // + // OnChangeState - change state. + // + void OnChangeState( + __in WIXSTDBA_STATE state + ) + { + WIXSTDBA_STATE stateOld = m_state; + DWORD dwOldPageId = 0; + DWORD dwNewPageId = 0; + LPWSTR sczText = NULL; + LPWSTR sczUnformattedText = NULL; + LPWSTR sczControlState = NULL; + LPWSTR sczControlName = NULL; + LOC_STRING* pLocString = NULL; + m_state = state; + + // If our install is at the end (success or failure) and we're not showing full UI or + // we successfully installed the prerequisite then exit (prompt for restart if required). + if ((WIXSTDBA_STATE_APPLIED <= m_state && BOOTSTRAPPER_DISPLAY_FULL > m_command.display) || + (WIXSTDBA_STATE_APPLIED == m_state && m_fPrereq)) + { + // If a restart was required but we were not automatically allowed to + // accept the reboot then do the prompt. + if (m_fRestartRequired && !m_fAllowRestart) + { + StrAllocFromError(&sczUnformattedText, HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED), NULL); + + int nResult = ::MessageBoxW(m_hWnd, sczUnformattedText ? sczUnformattedText : L"The requested operation is successful. Changes will not be effective until the system is rebooted.", m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OKCANCEL); + m_fAllowRestart = (IDOK == nResult); + } + + // Quietly exit. + ::PostMessageW(m_hWnd, WM_CLOSE, 0, 0); + } + else // try to change the pages. + { + DeterminePageId(stateOld, &dwOldPageId); + DeterminePageId(m_state, &dwNewPageId); + + if (dwOldPageId != dwNewPageId) + { + // Enable disable controls per-page. + if (m_rgdwPageIds[WIXSTDBA_PAGE_INSTALL] == dwNewPageId) // on the "Install" page, ensure the install button is enabled/disabled correctly. + { + LONGLONG llElevated = 0; + if (m_Bundle.fPerMachine) + { + BalGetNumericVariable(WIXBUNDLE_VARIABLE_ELEVATED, &llElevated); + } + ThemeControlElevates(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, (m_Bundle.fPerMachine && !llElevated)); + + // If the EULA control exists, show it only if a license URL is provided as well. + if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_EULA_LINK)) + { + BOOL fEulaLink = (m_sczLicenseUrl && *m_sczLicenseUrl); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_EULA_LINK, fEulaLink); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX, fEulaLink); + } + + BOOL fAcceptedLicense = !ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX) || !ThemeControlEnabled(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX) || ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, fAcceptedLicense); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_NEXT_BUTTON, fAcceptedLicense); + + // If there is an "Options" page, the "Options" button exists, and it hasn't been suppressed, then enable the button. + BOOL fOptionsEnabled = m_rgdwPageIds[WIXSTDBA_PAGE_INSTALLDIR] && ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_OPTIONS_BUTTON) && !m_fSuppressOptionsUI; + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_OPTIONS_BUTTON, fOptionsEnabled); + + // Show/Hide the version label if it exists. + if (m_rgdwPageIds[WIXSTDBA_PAGE_INSTALLDIR] && ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_VERSION_LABEL) && !m_fShowVersion) + { + ThemeShowControl(m_pTheme, WIXSTDBA_CONTROL_VERSION_LABEL, SW_HIDE); + } + } + else if (m_rgdwPageIds[WIXSTDBA_PAGE_MODIFY] == dwNewPageId) + { + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_REPAIR_BUTTON, !m_fSuppressRepair); + } + else if (m_rgdwPageIds[WIXSTDBA_PAGE_INSTALLDIR] == dwNewPageId) + { + HRESULT hr = BalGetStringVariable(WIXSTDBA_VARIABLE_INSTALL_FOLDER, &sczUnformattedText); + if (SUCCEEDED(hr)) + { + BalFormatString(sczUnformattedText, &sczText); + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX, sczText); + } + } + else if (m_rgdwPageIds[WIXSTDBA_PAGE_SUCCESS] == dwNewPageId) // on the "Success" page, check if the restart or launch button should be enabled. + { + BOOL fShowRestartButton = FALSE; + BOOL fLaunchTargetExists = FALSE; + + if (m_fIsRepair) + { + LocGetString(m_pWixLoc, L"#(loc.SuccessHeaderRepair)", &pLocString); + m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_SUCCESS_HEADER, pLocString->wzText); + LocGetString(m_pWixLoc, L"#(loc.SuccessInfoRepair)", &pLocString); + m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_SUCCESS_INFO, pLocString->wzText); + } + else if (m_fIsUninstall) + { + LocGetString(m_pWixLoc, L"#(loc.SuccessHeaderUninstall)", &pLocString); + m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_SUCCESS_HEADER, pLocString->wzText); + LocGetString(m_pWixLoc, L"#(loc.SuccessInfoUninstall)", &pLocString); + m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_SUCCESS_INFO, pLocString->wzText); + } + else + { + m_fInstallSucceed = TRUE; + + // If we have left some kind of error message file from MSI the show that + if (BalStringVariableExists(L"MSICustomErrFile")) + { + LPWSTR sczUnFormatedErrFile = NULL; + LPWSTR sczErrFile = NULL; + LPWSTR sczSuccessErrMsg = NULL; + FILE_ENCODING feEncodingFound = FILE_ENCODING_UNSPECIFIED; + + BalGetStringVariable(L"MSICustomErrFile", &sczUnFormatedErrFile); + BalFormatString(sczUnFormatedErrFile, &sczErrFile); + + if (SUCCEEDED(FileToString(sczErrFile, &sczSuccessErrMsg, &feEncodingFound))) + { + LocGetString(m_pWixLoc, L"#(loc.SuccessErrorInfoText)", &pLocString); + m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_SUCCESS_ERRINF, pLocString->wzText); + m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_SUCCESS_ERRMSG, sczSuccessErrMsg); + FileEnsureDelete(sczErrFile); + } + } + } + + if (m_fRestartRequired) + { + if (BOOTSTRAPPER_RESTART_PROMPT == m_command.restart) + { + fShowRestartButton = TRUE; + } + } + else if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_LAUNCH_BUTTON)) + { + fLaunchTargetExists = BalStringVariableExists(WIXSTDBA_VARIABLE_LAUNCH_TARGET_PATH); + } + + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_LAUNCH_BUTTON, fLaunchTargetExists && BOOTSTRAPPER_ACTION_UNINSTALL < m_plannedAction); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_SUCCESS_RESTART_TEXT, fShowRestartButton); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_SUCCESS_RESTART_BUTTON, fShowRestartButton); + } + else if (m_rgdwPageIds[WIXSTDBA_PAGE_FAILURE] == dwNewPageId) // on the "Failure" page, show error message and check if the restart button should be enabled. + { + BOOL fShowLogLink = (m_Bundle.sczLogVariable && *m_Bundle.sczLogVariable); // if there is a log file variable then we'll assume the log file exists. + BOOL fShowErrorMessage = FALSE; + BOOL fShowRestartButton = FALSE; + + if (m_fIsRepair) + { + LocGetString(m_pWixLoc, L"#(loc.FailureHeaderRepair)", &pLocString); + m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_FAILURE_HEADER, pLocString->wzText); + } + + if (m_fIsUninstall) + { + LocGetString(m_pWixLoc, L"#(loc.FailureHeaderUninstall)", &pLocString); + m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_FAILURE_HEADER, pLocString->wzText); + } + if (FAILED(m_hrFinal)) + { + // If we know the failure message, use that. + if (m_sczFailedMessage && *m_sczFailedMessage) + { + StrAllocString(&sczUnformattedText, m_sczFailedMessage, 0); + } + else // try to get the error message from the error code. + { + StrAllocFromError(&sczUnformattedText, m_hrFinal, NULL); + if (!sczUnformattedText || !*sczUnformattedText) + { + StrAllocFromError(&sczUnformattedText, E_FAIL, NULL); + } + } + + StrAllocFormatted(&sczText, L"0x%08x - %ls", m_hrFinal, sczUnformattedText); + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_FAILURE_MESSAGE_TEXT, sczText); + fShowErrorMessage = TRUE; + } + + if (m_fRestartRequired) + { + if (BOOTSTRAPPER_RESTART_PROMPT == m_command.restart) + { + fShowRestartButton = TRUE; + } + } + + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_FAILURE_LOGFILE_LINK, fShowLogLink); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_FAILURE_MESSAGE_TEXT, fShowErrorMessage); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_FAILURE_RESTART_TEXT, fShowRestartButton); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_FAILURE_RESTART_BUTTON, fShowRestartButton); + } + + // Hide the upgrade link + if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_UPGRADE_LINK)) + { + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_UPGRADE_LINK, FALSE); + } + + // Process each control for special handling in the new page. + THEME_PAGE* pPage = ThemeGetPage(m_pTheme, dwNewPageId); + if (pPage) + { + for (DWORD i = 0; i < pPage->cControlIndices; ++i) + { + THEME_CONTROL* pControl = m_pTheme->rgControls + pPage->rgdwControlIndices[i]; + + // If we are on the install, options or modify pages and this is a named control, try to set its default state. + if ((m_rgdwPageIds[WIXSTDBA_PAGE_INSTALL] == dwNewPageId || + m_rgdwPageIds[WIXSTDBA_PAGE_INSTALLDIR] == dwNewPageId || + m_rgdwPageIds[WIXSTDBA_PAGE_SVC_OPTIONS] == dwNewPageId || + m_rgdwPageIds[WIXSTDBA_PAGE_MODIFY] == dwNewPageId) && + pControl->sczName && *pControl->sczName) + { + // If this is a checkbox control, try to set its default state to the state of a matching named Burn variable. + if (THEME_CONTROL_TYPE_CHECKBOX == pControl->type && WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX != pControl->wId) + { + LONGLONG llValue = 0; + HRESULT hr = BalGetNumericVariable(pControl->sczName, &llValue); + + ThemeSendControlMessage(m_pTheme, pControl->wId, BM_SETCHECK, SUCCEEDED(hr) && llValue ? BST_CHECKED : BST_UNCHECKED, 0); + } + + // If this is a button control with the BS_AUTORADIOBUTTON style, try to set its default + // state to the state of a matching named Burn variable. + if (THEME_CONTROL_TYPE_BUTTON == pControl->type && (BS_AUTORADIOBUTTON == (BS_AUTORADIOBUTTON & pControl->dwStyle))) + { + LONGLONG llValue = 0; + HRESULT hr = BalGetNumericVariable(pControl->sczName, &llValue); + + // If the control value isn't set then disable it. + if (!SUCCEEDED(hr)) + { + ThemeControlEnable(m_pTheme, pControl->wId, FALSE); + } + else + { + ThemeSendControlMessage(m_pTheme, pControl->wId, BM_SETCHECK, SUCCEEDED(hr) && llValue ? BST_CHECKED : BST_UNCHECKED, 0); + } + } + + // Hide or disable controls based on the control name with 'State' appended + HRESULT hr = StrAllocFormatted(&sczControlName, L"%lsState", pControl->sczName); + if (SUCCEEDED(hr)) + { + hr = BalGetStringVariable(sczControlName, &sczControlState); + if (SUCCEEDED(hr) && sczControlState && *sczControlState) + { + if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, sczControlState, -1, L"disable", -1)) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Disable control %ls", pControl->sczName); + ThemeControlEnable(m_pTheme, pControl->wId, FALSE); + } + else if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, sczControlState, -1, L"hide", -1)) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Hide control %ls", pControl->sczName); + // TODO: This doesn't work + ThemeShowControl(m_pTheme, pControl->wId, SW_HIDE); + } + } + } + } + + // Format the text in each of the new page's controls (if they have any text). + if (pControl->sczText && *pControl->sczText) + { + HRESULT hr = BalFormatString(pControl->sczText, &sczText); + if (SUCCEEDED(hr)) + { + ThemeSetTextControl(m_pTheme, pControl->wId, sczText); + } + } + } + } + + ThemeShowPage(m_pTheme, dwOldPageId, SW_HIDE); + ThemeShowPage(m_pTheme, dwNewPageId, SW_SHOW); + + + // Remember current page + m_dwCurrentPage = dwNewPageId; + + // On the install page set the focus to the install button or the next enabled control if install is disabled + if (m_rgdwPageIds[WIXSTDBA_PAGE_INSTALL] == dwNewPageId) + { + HWND hwndFocus = ::GetDlgItem(m_pTheme->hwndParent, WIXSTDBA_CONTROL_INSTALL_BUTTON); + if (hwndFocus && !ThemeControlEnabled(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON)) + { + hwndFocus = ::GetNextDlgTabItem(m_pTheme->hwndParent, hwndFocus, FALSE); + } + + if (hwndFocus) + { + ::SetFocus(hwndFocus); + } + } + } + } + + ReleaseStr(sczText); + ReleaseStr(sczUnformattedText); + ReleaseStr(sczControlState); + ReleaseStr(sczControlName); + } + + + // + // OnClose - called when the window is trying to be closed. + // + BOOL OnClose() + { + BOOL fClose = FALSE; + + // If we've already succeeded or failed or showing the help page, just close (prompts are annoying if the bootstrapper is done). + if (WIXSTDBA_STATE_APPLIED <= m_state || WIXSTDBA_STATE_HELP == m_state) + { + fClose = TRUE; + } + else // prompt the user or force the cancel if there is no UI. + { + fClose = PromptCancel(m_hWnd, BOOTSTRAPPER_DISPLAY_FULL != m_command.display, m_sczConfirmCloseMessage ? m_sczConfirmCloseMessage : L"Are you sure you want to cancel?", m_pTheme->sczCaption); + } + + // If we're doing progress then we never close, we just cancel to let rollback occur. + if (WIXSTDBA_STATE_APPLYING <= m_state && WIXSTDBA_STATE_APPLIED > m_state) + { + // If we canceled disable cancel button since clicking it again is silly. + if (fClose) + { + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_PROGRESS_CANCEL_BUTTON, FALSE); + } + + fClose = FALSE; + } + + return fClose; + } + + + // + // OnClickAcceptCheckbox - allow the install to continue. + // + void OnClickAcceptCheckbox() + { + BOOL fAcceptedLicense = ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_EULA_ACCEPT_CHECKBOX); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, fAcceptedLicense); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_NEXT_BUTTON, fAcceptedLicense); + } + + + // + // OnClickOptionsButton - show the options page. + // + void OnClickOptionsButton() + { + SavePageSettings(WIXSTDBA_PAGE_INSTALL); + m_stateInstallPage = m_state; + SetState(WIXSTDBA_STATE_INSTALLDIR, S_OK); + } + + + BOOL CheckNonEmptyField(LPCWSTR wzEditVarID) + { + BOOL bRes = TRUE; + LPWSTR sczFieldValue = NULL; + + if (SUCCEEDED(BalGetStringVariable(wzEditVarID, &sczFieldValue))) + { + if (StrCmpCW(sczFieldValue, L"") == 0) + { + LOC_STRING* pLocString = NULL; + LPWSTR wzLoc = NULL; + LPWSTR sczMessageText = NULL; + + StrAllocFormatted(&wzLoc, L"#(loc.%s)", wzEditVarID); + LocGetString(m_pWixLoc, wzLoc, &pLocString); + StrAllocFormatted(&sczMessageText, L"The field \"%s\" cannot be blank! In order to continue with setup you should fill it.", pLocString->wzText); + + ::MessageBoxW(m_hWnd, sczMessageText, m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OK); + bRes = FALSE; + } + } + return bRes; + } + + + + + BOOL CheckCurrentUserPassword(LPCWSTR wzPasswordVarID) + { + LPWSTR sczUserNameValue = NULL; + LPWSTR sczDomainValue = NULL; + LPWSTR sczPasswordValue = NULL; + + BOOL bRes = SUCCEEDED(BalGetStringVariable(L"ComputerName", &sczDomainValue)) && + SUCCEEDED(BalGetStringVariable(L"LogonUser", &sczUserNameValue)) && + SUCCEEDED(BalGetStringVariable(wzPasswordVarID, &sczPasswordValue)); + + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "CheckCurrentUserPassword. 1"); + + + if (bRes) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "CheckCurrentUserPassword. 2"); + HANDLE hToken; + if (!LogonUserW(sczUserNameValue, sczDomainValue, sczPasswordValue, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &hToken)) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "CheckCurrentUserPassword. 3 - Failed"); + + LPWSTR sczMessageText = NULL; + StrAllocFormatted(&sczMessageText, L"Setup was unable to validate specified password for \"%s\\%s\"! Please double check it.", sczDomainValue, sczUserNameValue); + + ::MessageBoxW(m_hWnd, sczMessageText, m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OK); + bRes = FALSE; + } + else + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "CheckCurrentUserPassword. 4 - Succeed"); + } + } + return bRes; + } + + + + + + /* + + BOOL CheckPostgreSQLConnection(LPCWSTR VAR_HOST, LPCWSTR VAR_USER, LPCWSTR VAR_PASS, LPCWSTR DB_ToCheck, BOOL DB_ShouldExists) + { + BOOL bPSQLOk = CheckNonEmptyField(VAR_HOST) && CheckNonEmptyField(VAR_USER) && CheckNonEmptyField(VAR_PASS); + +// if (!bPSQLOk) return FALSE; + + LPWSTR sczPSQLPath = NULL; + LPWSTR sczPSQLDirectory = NULL; + + if (bPSQLOk && SUCCEEDED(PathRelativeToModule(&sczPSQLPath, L"qcPSQL.exe", m_hModule)) && SUCCEEDED(PathGetDirectory(sczPSQLPath, &sczPSQLDirectory))) + { + LPWSTR sczPSQLHost = NULL; + LPWSTR sczPSQLUser = NULL; + LPWSTR sczPSQLPass = NULL; + + if (SUCCEEDED(BalGetStringVariable(VAR_HOST, &sczPSQLHost)) && + SUCCEEDED(BalGetStringVariable(VAR_USER, &sczPSQLUser)) && + SUCCEEDED(BalGetStringVariable(VAR_PASS, &sczPSQLPass)) ) + { + DWORD exitcode = 0; + LPWSTR sczCmdParam = NULL; + if (DB_ToCheck == NULL) + StrAllocFormatted(&sczCmdParam, L"\"%s\" checkconnection -H%s -U%s -P%s", sczPSQLPath, sczPSQLHost, sczPSQLUser, sczPSQLPass); + else + StrAllocFormatted(&sczCmdParam, L"\"%s\" checkdbexists -H%s -U%s -P%s -CKDB%s", sczPSQLPath, sczPSQLHost, sczPSQLUser, sczPSQLPass, DB_ToCheck); + + _STARTUPINFOW si; + _PROCESS_INFORMATION pi; + + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof(si); + ZeroMemory( &pi, sizeof(pi) ); + + + // Start the child process. + if( CreateProcessW(NULL, // No module name (use command line) + sczCmdParam, // Command line + NULL, // Process handle not inheritable + NULL, // Thread handle not inheritable + FALSE, // Set handle inheritance to FALSE + CREATE_NO_WINDOW, // No creation flags + NULL, // Use parent's environment block + NULL, // Use parent's starting directory + &si, // Pointer to STARTUPINFO structure + &pi ) // Pointer to PROCESS_INFORMATION structure + ) + { + // Wait until child process exits. + WaitForSingleObject( pi.hProcess, INFINITE ); + + // get the process exit code + GetExitCodeProcess(pi.hProcess, (LPDWORD)&exitcode); + + // Close process and thread handles. + CloseHandle( pi.hProcess ); + CloseHandle( pi.hThread ); + } + + + + LPWSTR sczMessageText = NULL; + switch (exitcode) + { + case QCPSQL_ERROR_UNKNOWN: + sczMessageText = L"Setup was unable to connect to the specified database server. Unknown error.\nWould you like to continue anyway?"; + break; + case QCPSQL_ERROR_EXECSQL: + sczMessageText = L"Setup was unable to execute specified command.\nWould you like to continue anyway?"; + break; + case QCPSQL_ERROR_CONNECT: + sczMessageText = L"Setup was unable to connect to the specified database server.\nWould you like to continue anyway?"; + break; + case QCPSQL_ERROR_INVALIDARGS: + sczMessageText = L"Setup was unable to connect to the specified database server. Invalid arguments.\nWould you like to continue anyway?"; + break; + case QCPSQL_SUCCESS_DBNOTEXISTS: + if ((DB_ToCheck != NULL) && (DB_ShouldExists)) + StrAllocFormatted(&sczMessageText, L"The database \"%s\" does not exists on the host \"%s\".\nWould you like to continue anyway?", DB_ToCheck, sczPSQLHost); + break; + case QCPSQL_SUCCESS_DBEXISTS: + if ((DB_ToCheck != NULL) && (!DB_ShouldExists)) + StrAllocFormatted(&sczMessageText, L"The database \"%s\" already exists on the host \"%s\".\nWould you like to continue anyway?", DB_ToCheck, sczPSQLHost); + break; + default: + break; + } + + if (sczMessageText != NULL) + bPSQLOk = (IDYES == ::MessageBoxW(m_hWnd, sczMessageText, m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_YESNO)); + } + } + + return bPSQLOk; + } + */ + + BOOL CheckInstallPathIsValid(LPCWSTR wzInstallPath) + { + BOOL bPathIsValid = TRUE; + + if (StrCmpCW(wzInstallPath, L"") == 0) + { + bPathIsValid = FALSE; + ::MessageBoxW(m_hWnd, L"The install location cannot be blank. You must enter a full path with drive letter, like:\n\tC:\\Program Files\\App\n\nor a UNC path, like\n\t\\\\ServerName\\AppShare", m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OK); + } else { + DWORD i = 0; + LPCWSTR wz = wzInstallPath; + BOOL bInvalidCharFound = FALSE; + while (*wz) + { + ++i; + if ((L'/' == *wz) || ((L':' == *wz) && (i != 2)) || (L'*' == *wz) || (L'?' == *wz) || + (L'"' == *wz) || (L'<' == *wz) || (L'>' == *wz) || (L'|' == *wz)) + bInvalidCharFound = TRUE; + ++wz; + } + + if (bInvalidCharFound) + { + bPathIsValid = FALSE; + ::MessageBoxW(m_hWnd, L"The install location cannot include any of the following characters:\n\n/ : * ? \" < > |", m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OK); + } + } + return bPathIsValid; + } + + + BOOL CheckEmailAddressIsValid(LPCWSTR wzEmailVarID, LPCWSTR wzPassVarID = NULL, BOOL AllowBlank = TRUE) + { + BOOL bRes = TRUE; + LPWSTR sczEmailValue = NULL; + LPWSTR sczPassValue = NULL; + + if (SUCCEEDED(BalGetStringVariable(wzEmailVarID, &sczEmailValue))) + { + LOC_STRING* pLocString = NULL; + LPWSTR wzLoc = NULL; + LPWSTR sczMessageText = NULL; + + StrAllocFormatted(&wzLoc, L"#(loc.%s)", wzEmailVarID); + LocGetString(m_pWixLoc, wzLoc, &pLocString); + + BOOL bIsBlank = (StrCmpCW(sczEmailValue, L"") == 0); + + if (bIsBlank && AllowBlank) + return TRUE; + + if (bIsBlank) + { + bRes = FALSE; + StrAllocFormatted(&sczMessageText, L"The field \"%s\" cannot be blank! In order to continue with setup you should fill it.", pLocString->wzText); + } else { + DWORD i = 0; + DWORD iAt = 0; + DWORD iPt = 0; + + LPCWSTR wz = sczEmailValue; + while (*wz) + { + ++i; + if (L'@' == *wz) iAt = i; + if (L'.' == *wz) iPt = i; + ++wz; + } + bRes = (1 < iAt) && (iAt < iPt); + + if (!bRes) + StrAllocFormatted(&sczMessageText, L"The field \"%s\" dosen't seems to be a valid email address! Please double check that.", pLocString->wzText); + } + + if (!bRes) + ::MessageBoxW(m_hWnd, sczMessageText, m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OK); + else { + if (wzPassVarID != NULL) + { + if (SUCCEEDED(BalGetStringVariable(wzPassVarID, &sczPassValue))) + if (StrCmpCW(sczEmailValue, L"") == 0) { + bRes = FALSE; + ::MessageBoxW(m_hWnd, L"You specified a valid email address but the account password is blank. The password is required!", m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OK); + } + } + } + + } + + return bRes; + } + + + void OnClickNextButton() + { + BOOL bOkToContinue = TRUE; + LPWSTR sczPath = NULL; + + switch (m_state) + { + case WIXSTDBA_STATE_INSTALLDIR: + ThemeGetTextControl(m_pTheme, WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX, &sczPath); + bOkToContinue = CheckInstallPathIsValid(sczPath); + + if (bOkToContinue) { + m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_INSTALL_FOLDER, sczPath); + SavePageSettings(WIXSTDBA_PAGE_INSTALLDIR); + SetState(WIXSTDBA_STATE_SVC_OPTIONS, S_OK); + + // Display the elevation shield if perMachine installation + LONGLONG llElevated = 0; + if (SUCCEEDED(BalGetNumericVariable(WIXSTDBA_VARIABLE_PERMACHINE_INSTALL, &llElevated))) + ThemeControlElevates(m_pTheme, WIXSTDBA_CONTROL_INSTALL_BUTTON, (llElevated == 1)); + } + break; + + default: + SavePageSettings(WIXSTDBA_PAGE_INSTALL); + m_stateInstallPage = m_state; + SetState(WIXSTDBA_STATE_INSTALLDIR, S_OK); + break; + } + } + + + // + // OnClickInstallScope - allow user to choose between a perMachine and perUser install + // + void OnClickInstallScope() + { + LPWSTR sczPath = NULL; + LPWSTR sczFPath = NULL; + BOOL fPerMachineInst = ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_PERMACHINE_RADIO); + + + if (fPerMachineInst) + { + if (SUCCEEDED(BalGetStringVariable(WIXSTDBA_VARIABLE_PERMACHINE_INSTALL_FOLDER, &sczPath)) + && SUCCEEDED(BalFormatString(sczPath, &sczFPath))) + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX, sczFPath); + } + else + { + if (SUCCEEDED(BalGetStringVariable(WIXSTDBA_VARIABLE_PERUSER_INSTALL_FOLDER, &sczPath)) + && SUCCEEDED(BalFormatString(sczPath, &sczFPath))) + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX, sczFPath); + } + } + + // + // OnClickInstallPostgressCheckbox - we will set defaults value and disable controls if checkbox was checked. + // + void OnClickSkipRegistrationCheckbox() + { + BOOL fSkipReg = ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_SKIPREG_CHECKBOX); + BOOL fSignIn = ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_REGSIGNIN_RADIO); + + //if (fSkipReg) + //{ + // ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_DBHOST_EDIT, L"localhost"); + // ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_DBUSER_EDIT, L"postgres"); + // ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_DBPASS_EDIT, L"postgres"); + //} + + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_REGMAIL_LABEL, !fSkipReg && !fSignIn); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_REGUSER_LABEL, !fSkipReg); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_REGPASS_LABEL, !fSkipReg); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_REGMAIL_EDIT, !fSkipReg && !fSignIn); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_REGUSER_EDIT, !fSkipReg); + ThemeControlEnable(m_pTheme, WIXSTDBA_CONTROL_REGPASS_EDIT, !fSkipReg); + } + + + + // + // OnClickInstallButton - start the install by planning the packages. + // + void OnClickInstallButton() + { + m_fOverallInstallationStarted = TRUE; + BOOL bOkToContinue = TRUE; + BOOL fSignIn = ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_REGSIGNIN_RADIO); + BOOL fSkipReg = ThemeIsControlChecked(m_pTheme, WIXSTDBA_CONTROL_SKIPREG_CHECKBOX); + + SavePageSettings(WIXSTDBA_PAGE_SVC_OPTIONS); + + if (!fSkipReg) + { + bOkToContinue = CheckNonEmptyField(WIXSTDBA_VARIABLE_REG_USER) && CheckNonEmptyField(WIXSTDBA_VARIABLE_REG_PASS); + if (bOkToContinue) + { + if (fSignIn) + { + LPWSTR wzUserName = NULL; + LPWSTR wzUserPass = NULL; + if (SUCCEEDED(BalGetStringVariable(WIXSTDBA_VARIABLE_REG_USER, &wzUserName)) && + SUCCEEDED(BalGetStringVariable(WIXSTDBA_VARIABLE_REG_PASS, &wzUserPass))) + { + bOkToContinue = REST_ValidateUserLogin(wzUserName, wzUserPass); + } + } + else + { + bOkToContinue = CheckNonEmptyField(WIXSTDBA_VARIABLE_REG_MAIL) && CheckEmailAddressIsValid(WIXSTDBA_VARIABLE_REG_MAIL); + MessageBoxW(m_hWnd, L"Creating a meteor developer account from here it wasn't implemnted yet.", m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OK); + } + } + } + + SavePageSettings(WIXSTDBA_PAGE_INSTALL); + + if (bOkToContinue) this->OnPlan(BOOTSTRAPPER_ACTION_INSTALL); + } + + + void OnClickBackButton() + { + BOOL bOkToContinue = TRUE; + LPWSTR sczPath = NULL; + + switch (m_state) + { + case WIXSTDBA_STATE_INSTALLDIR: + ThemeGetTextControl(m_pTheme, WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX, &sczPath); + bOkToContinue = CheckInstallPathIsValid(sczPath); + + if (bOkToContinue) { + m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_INSTALL_FOLDER, sczPath); + SavePageSettings(WIXSTDBA_PAGE_INSTALLDIR); + SetState(m_stateInstallPage, S_OK); + } + + break; + + case WIXSTDBA_STATE_SVC_OPTIONS: + SavePageSettings(WIXSTDBA_PAGE_SVC_OPTIONS); + SetState(WIXSTDBA_STATE_INSTALLDIR, S_OK); + break; + } + + } + + + // + // OnClickOptionsBrowseButton - browse for install folder on the options page. + // + void OnClickOptionsBrowseButton(DWORD dwControl) + { + WCHAR wzPath[MAX_PATH] = { }; + BROWSEINFOW browseInfo = { }; + PIDLIST_ABSOLUTE pidl = NULL; + PIDLIST_ABSOLUTE pidlRoot = NULL; + + ::SHGetFolderLocation(m_hWnd, CSIDL_DRIVES, NULL, 0, &pidlRoot); + + browseInfo.hwndOwner = m_hWnd; + browseInfo.pszDisplayName = wzPath; + browseInfo.lpszTitle = m_pTheme->sczCaption; + browseInfo.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI; + browseInfo.pidlRoot = pidlRoot; + pidl = ::SHBrowseForFolderW(&browseInfo); + if (pidl && ::SHGetPathFromIDListW(pidl, wzPath)) + { + switch (dwControl) + { + case WIXSTDBA_CONTROL_BROWSE_BUTTON: + ThemeSetTextControl(m_pTheme, WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX, wzPath); + break; + } + } + + if (pidl) + { + ::CoTaskMemFree(pidl); + } + + return; + } + + // + // OnClickOptionsOkButton - accept the changes made by the options page. + // + void OnClickOptionsOkButton() + { + HRESULT hr = S_OK; + LPWSTR sczPath = NULL; + + if (ThemeControlExists(m_pTheme, WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX)) + { + hr = ThemeGetTextControl(m_pTheme, WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX, &sczPath); + ExitOnFailure(hr, "Failed to get text from folder edit box."); + + // TODO: verify the path is valid. + + hr = m_pEngine->SetVariableString(WIXSTDBA_VARIABLE_INSTALL_FOLDER, sczPath); + ExitOnFailure(hr, "Failed to set the install folder."); + } + + + SavePageSettings(WIXSTDBA_PAGE_INSTALLDIR); + +LExit: + SetState(m_stateInstallPage, S_OK); + return; + } + + + // + // OnClickOptionsCancelButton - discard the changes made by the options page. + // + void OnClickOptionsCancelButton() + { + SetState(m_stateInstallPage, S_OK); + } + + + // + // OnClickRepairButton - start the repair. + // + void OnClickRepairButton() + { + this->OnPlan(BOOTSTRAPPER_ACTION_REPAIR); + } + + + // + // OnClickUninstallButton - start the uninstall. + // + void OnClickUninstallButton() + { + this->OnPlan(BOOTSTRAPPER_ACTION_UNINSTALL); + } + + + + void TryLaunchAfterInstall(LPWSTR wzVarTargetPath) + { + BOOL fLaunchAfterInstallTargetExists = BalStringVariableExists(wzVarTargetPath); + + HRESULT hr = S_OK; + LPWSTR sczUnformattedLaunchTarget = NULL; + LPWSTR sczLaunchTarget = NULL; + LPWSTR sczUnformattedArguments = NULL; + LPWSTR sczArguments = NULL; + LPWSTR sczRunOnceValue = NULL; + + int nCmdShow = SW_SHOWNORMAL; + + if (fLaunchAfterInstallTargetExists) + { + hr = BalGetStringVariable(wzVarTargetPath, &sczUnformattedLaunchTarget); + hr = BalFormatString(sczUnformattedLaunchTarget, &sczLaunchTarget); + } + + if (m_fInstallSucceed && fLaunchAfterInstallTargetExists) + { + + if (!m_fRestartRequired) + { + DWORD dwAttr; + if (FileExistsEx(sczLaunchTarget, &dwAttr)) + ShelExec(sczLaunchTarget, sczArguments, L"open", NULL, nCmdShow, m_hWnd, NULL); + } + } + + ReleaseStr(sczUnformattedLaunchTarget); + ReleaseStr(sczLaunchTarget); + ReleaseStr(sczUnformattedArguments); + ReleaseStr(sczArguments); + ReleaseStr(sczRunOnceValue); + + return; + } + + // + // OnClickCloseButton - close the application. + // + void OnClickCloseButton() + { + TryLaunchAfterInstall(L"Launch_IISStartServerPath"); + TryLaunchAfterInstall(L"Launch_EverywarePOSPath"); + ::SendMessageW(m_hWnd, WM_CLOSE, 0, 0); + return; + } + + + // + // OnClickEulaLink - show the end user license agreement. + // + void OnClickEulaLink() + { + HRESULT hr = S_OK; + LPWSTR sczLicenseUrl = NULL; + LPWSTR sczLicensePath = NULL; + LPWSTR sczLicenseDirectory = NULL; + URI_PROTOCOL protocol = URI_PROTOCOL_UNKNOWN; + + hr = StrAllocString(&sczLicenseUrl, m_sczLicenseUrl, 0); + BalExitOnFailure1(hr, "Failed to copy license URL: %ls", m_sczLicenseUrl); + + hr = LocLocalizeString(m_pWixLoc, &sczLicenseUrl); + BalExitOnFailure1(hr, "Failed to localize license URL: %ls", m_sczLicenseUrl); + + hr = BalFormatString(sczLicenseUrl, &sczLicenseUrl); + BalExitOnFailure1(hr, "Failed to get formatted license URL: %ls", m_sczLicenseUrl); + + hr = UriProtocol(sczLicenseUrl, &protocol); + if (FAILED(hr) || URI_PROTOCOL_UNKNOWN == protocol) + { + // Probe for localised license file + hr = PathRelativeToModule(&sczLicensePath, sczLicenseUrl, m_hModule); + if (SUCCEEDED(hr)) + { + hr = PathGetDirectory(sczLicensePath, &sczLicenseDirectory); + if (SUCCEEDED(hr)) + { + hr = LocProbeForFile(sczLicenseDirectory, PathFile(sczLicenseUrl), m_sczLanguage, &sczLicensePath); + } + } + } + + hr = ShelExec(sczLicensePath ? sczLicensePath : sczLicenseUrl, NULL, L"open", NULL, SW_SHOWDEFAULT, m_hWnd, NULL); + BalExitOnFailure(hr, "Failed to launch URL to EULA."); + +LExit: + ReleaseStr(sczLicensePath); + ReleaseStr(sczLicenseUrl); + ReleaseStr(sczLicenseDirectory); + + return; + } + + + // + // OnClickUpgradeLink - download the upgrade. + // + void OnClickUpgradeLink() + { + this->OnPlan(BOOTSTRAPPER_ACTION_UPDATE_REPLACE); + + m_fUpdating = TRUE; + + return; + } + + + // + // OnClickLaunchButton - launch the app from the success page. + // + void OnClickLaunchButton() + { + HRESULT hr = S_OK; + LPWSTR sczUnformattedLaunchTarget = NULL; + LPWSTR sczLaunchTarget = NULL; + LPWSTR sczUnformattedArguments = NULL; + LPWSTR sczArguments = NULL; + int nCmdShow = SW_SHOWNORMAL; + + hr = BalGetStringVariable(WIXSTDBA_VARIABLE_LAUNCH_TARGET_PATH, &sczUnformattedLaunchTarget); + BalExitOnFailure1(hr, "Failed to get launch target variable '%ls'.", WIXSTDBA_VARIABLE_LAUNCH_TARGET_PATH); + + hr = BalFormatString(sczUnformattedLaunchTarget, &sczLaunchTarget); + BalExitOnFailure1(hr, "Failed to format launch target variable: %ls", sczUnformattedLaunchTarget); + + if (BalStringVariableExists(WIXSTDBA_VARIABLE_LAUNCH_ARGUMENTS)) + { + hr = BalGetStringVariable(WIXSTDBA_VARIABLE_LAUNCH_ARGUMENTS, &sczUnformattedArguments); + BalExitOnFailure1(hr, "Failed to get launch arguments '%ls'.", WIXSTDBA_VARIABLE_LAUNCH_ARGUMENTS); + + hr = BalFormatString(sczUnformattedArguments, &sczArguments); + BalExitOnFailure1(hr, "Failed to format launch arguments variable: %ls", sczUnformattedArguments); + } + + if (BalStringVariableExists(WIXSTDBA_VARIABLE_LAUNCH_HIDDEN)) + { + nCmdShow = SW_HIDE; + } + + hr = ShelExec(sczLaunchTarget, sczArguments, L"open", NULL, nCmdShow, m_hWnd, NULL); + BalExitOnFailure1(hr, "Failed to launch target: %ls", sczLaunchTarget); + + ::PostMessageW(m_hWnd, WM_CLOSE, 0, 0); + +LExit: + ReleaseStr(sczLaunchTarget); + ReleaseStr(sczUnformattedLaunchTarget); + ReleaseStr(sczArguments); + ReleaseStr(sczUnformattedArguments); + + return; + } + + + // + // OnClickRestartButton - allows the restart and closes the app. + // + void OnClickRestartButton() + { + AssertSz(m_fRestartRequired, "Restart must be requested to be able to click on the restart button."); + + m_fAllowRestart = TRUE; + ::SendMessageW(m_hWnd, WM_CLOSE, 0, 0); + + return; + } + + + // + // OnClickLogFileLink - show the log file. + // + void OnClickLogFileLink() + { + HRESULT hr = S_OK; + LPWSTR sczLogFile = NULL; + + hr = BalGetStringVariable(m_Bundle.sczLogVariable, &sczLogFile); + BalExitOnFailure1(hr, "Failed to get log file variable '%ls'.", m_Bundle.sczLogVariable); + + hr = ShelExec(L"notepad.exe", sczLogFile, L"open", NULL, SW_SHOWDEFAULT, m_hWnd, NULL); + BalExitOnFailure1(hr, "Failed to open log file target: %ls", sczLogFile); + +LExit: + ReleaseStr(sczLogFile); + + return; + } + + + // + // SetState + // + void SetState( + __in WIXSTDBA_STATE state, + __in HRESULT hrStatus + ) + { + if (FAILED(hrStatus)) + { + m_hrFinal = hrStatus; + } + + if (FAILED(m_hrFinal)) + { + state = WIXSTDBA_STATE_FAILED; + } + + if (WIXSTDBA_STATE_INSTALLDIR == state || m_state < state) + { + ::PostMessageW(m_hWnd, WM_WIXSTDBA_CHANGE_STATE, 0, state); + } + + if (WIXSTDBA_STATE_INSTALLDIR == state || m_state < state) + { + ::PostMessageW(m_hWnd, WM_WIXSTDBA_CHANGE_STATE, 0, state); + } + + if (WIXSTDBA_STATE_SVC_OPTIONS == state || m_state < state) + { + ::PostMessageW(m_hWnd, WM_WIXSTDBA_CHANGE_STATE, 0, state); + } + } + + + void DeterminePageId( + __in WIXSTDBA_STATE state, + __out DWORD* pdwPageId + ) + { + if (BOOTSTRAPPER_DISPLAY_PASSIVE == m_command.display) + { + switch (state) + { + case WIXSTDBA_STATE_INITIALIZED: + *pdwPageId = BOOTSTRAPPER_ACTION_HELP == m_command.action ? m_rgdwPageIds[WIXSTDBA_PAGE_HELP] : m_rgdwPageIds[WIXSTDBA_PAGE_LOADING]; + break; + + case WIXSTDBA_STATE_HELP: + *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_HELP]; + break; + + case WIXSTDBA_STATE_DETECTING: + *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_LOADING] ? m_rgdwPageIds[WIXSTDBA_PAGE_LOADING] : m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS_PASSIVE] ? m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS_PASSIVE] : m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS]; + break; + + case WIXSTDBA_STATE_DETECTED: __fallthrough; + case WIXSTDBA_STATE_PLANNING: __fallthrough; + case WIXSTDBA_STATE_PLANNED: __fallthrough; + case WIXSTDBA_STATE_APPLYING: __fallthrough; + case WIXSTDBA_STATE_CACHING: __fallthrough; + case WIXSTDBA_STATE_CACHED: __fallthrough; + case WIXSTDBA_STATE_EXECUTING: __fallthrough; + case WIXSTDBA_STATE_EXECUTED: + *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS_PASSIVE] ? m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS_PASSIVE] : m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS]; + break; + + default: + *pdwPageId = 0; + break; + } + } + else if (BOOTSTRAPPER_DISPLAY_FULL == m_command.display) + { + switch (state) + { + case WIXSTDBA_STATE_INITIALIZING: + *pdwPageId = 0; + break; + + case WIXSTDBA_STATE_INITIALIZED: + *pdwPageId = BOOTSTRAPPER_ACTION_HELP == m_command.action ? m_rgdwPageIds[WIXSTDBA_PAGE_HELP] : m_rgdwPageIds[WIXSTDBA_PAGE_LOADING]; + break; + + case WIXSTDBA_STATE_HELP: + *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_HELP]; + break; + + case WIXSTDBA_STATE_DETECTING: + *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_LOADING]; + break; + + case WIXSTDBA_STATE_DETECTED: + switch (m_command.action) + { + case BOOTSTRAPPER_ACTION_INSTALL: + *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_INSTALL]; + break; + + case BOOTSTRAPPER_ACTION_MODIFY: __fallthrough; + case BOOTSTRAPPER_ACTION_REPAIR: __fallthrough; + case BOOTSTRAPPER_ACTION_UNINSTALL: + *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_MODIFY]; + break; + } + break; + + case WIXSTDBA_STATE_INSTALLDIR: + *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_INSTALLDIR]; + break; + + case WIXSTDBA_STATE_SVC_OPTIONS: + *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_SVC_OPTIONS]; + break; + + case WIXSTDBA_STATE_PLANNING: __fallthrough; + case WIXSTDBA_STATE_PLANNED: __fallthrough; + case WIXSTDBA_STATE_APPLYING: __fallthrough; + case WIXSTDBA_STATE_CACHING: __fallthrough; + case WIXSTDBA_STATE_CACHED: __fallthrough; + case WIXSTDBA_STATE_EXECUTING: __fallthrough; + case WIXSTDBA_STATE_EXECUTED: + *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_PROGRESS]; + break; + + case WIXSTDBA_STATE_APPLIED: + *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_SUCCESS]; + CopyBundleLogToSpecifiedPath(); + break; + + case WIXSTDBA_STATE_FAILED: + *pdwPageId = m_rgdwPageIds[WIXSTDBA_PAGE_FAILURE]; + CopyBundleLogToSpecifiedPath(); + break; + } + } + } + + + HRESULT EvaluateConditions() + { + HRESULT hr = S_OK; + BOOL fResult = FALSE; + + for (DWORD i = 0; i < m_Conditions.cConditions; ++i) + { + BAL_CONDITION* pCondition = m_Conditions.rgConditions + i; + + hr = BalConditionEvaluate(pCondition, m_pEngine, &fResult, &m_sczFailedMessage); + BalExitOnFailure(hr, "Failed to evaluate condition."); + + if (!fResult) + { + hr = E_WIXSTDBA_CONDITION_FAILED; + BalExitOnFailure1(hr, "Bundle condition evaluated to false: %ls", pCondition->sczCondition); + } + } + + ReleaseNullStr(m_sczFailedMessage); + +LExit: + return hr; + } + + + + void CopyBundleLogToSpecifiedPath() + { + /// On package install complete, if WIXSTDBA_VARIABLE_LOGSPATH is defined + /// then will move bundle installation log to the specified path. + if (!m_fOverallInstallationStarted) + return; + + if (BalStringVariableExists(WIXSTDBA_VARIABLE_LOGSPATH)) + { + LPWSTR wzBundleLog = NULL; + LPWSTR wzInstallLogPath = NULL; + LPWSTR wzDstBundleLog = NULL; + + if ( SUCCEEDED(BalGetStringVariable(WIXSTDBA_VARIABLE_LOGSPATH, &wzInstallLogPath)) && + SUCCEEDED(BalGetStringVariable(L"WixBundleLog", &wzBundleLog))) + { + StrAllocFormatted(&wzDstBundleLog, L"%s\\%s", wzInstallLogPath, PathFile(wzBundleLog)); + DirEnsureExists(wzInstallLogPath, NULL); + FileEnsureCopy(wzBundleLog, wzDstBundleLog, TRUE); + } else + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Setup was unable to copy bundle log to the specified installation log path."); + } + + return; + } + + + + void SetTaskbarButtonProgress( + __in DWORD dwOverallPercentage + ) + { + HRESULT hr = S_OK; + + if (m_fTaskbarButtonOK) + { + hr = m_pTaskbarList->SetProgressValue(m_hWnd, dwOverallPercentage, 100UL); + BalExitOnFailure1(hr, "Failed to set taskbar button progress to: %d%%.", dwOverallPercentage); + } + +LExit: + return; + } + + + void SetTaskbarButtonState( + __in TBPFLAG tbpFlags + ) + { + HRESULT hr = S_OK; + + if (m_fTaskbarButtonOK) + { + hr = m_pTaskbarList->SetProgressState(m_hWnd, tbpFlags); + BalExitOnFailure1(hr, "Failed to set taskbar button state.", tbpFlags); + } + +LExit: + return; + } + + + void SetProgressState( + __in HRESULT hrStatus + ) + { + TBPFLAG flag = TBPF_NORMAL; + + if (IsCanceled() || HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) == hrStatus) + { + flag = TBPF_PAUSED; + } + else if (IsRollingBack() || FAILED(hrStatus)) + { + flag = TBPF_ERROR; + } + + SetTaskbarButtonState(flag); + } + + + void SavePageSettings( + __in WIXSTDBA_PAGE page + ) + { + THEME_PAGE* pPage = NULL; + + pPage = ThemeGetPage(m_pTheme, m_rgdwPageIds[page]); + if (pPage) + { + for (DWORD i = 0; i < pPage->cControlIndices; ++i) + { + // Loop through all the checkbox controls (or buttons with BS_AUTORADIOBUTTON) with names and set a Burn variable with that name to true or false. + THEME_CONTROL* pControl = m_pTheme->rgControls + pPage->rgdwControlIndices[i]; + if ((THEME_CONTROL_TYPE_CHECKBOX == pControl->type) || + (THEME_CONTROL_TYPE_BUTTON == pControl->type && (BS_AUTORADIOBUTTON == (BS_AUTORADIOBUTTON & pControl->dwStyle)) && + pControl->sczName && *pControl->sczName)) + { + BOOL bChecked = ThemeIsControlChecked(m_pTheme, pControl->wId); + m_pEngine->SetVariableNumeric(pControl->sczName, bChecked ? 1 : 0); + } + + // Loop through all the editbox controls with names and set a Burn variable with that name to the contents. + if (THEME_CONTROL_TYPE_EDITBOX == pControl->type && pControl->sczName && *pControl->sczName && + (WIXSTDBA_CONTROL_INSTALLFOLDER_EDITBOX != pControl->wId)) + { + LPWSTR sczValue = NULL; + ThemeGetTextControl(m_pTheme, pControl->wId, &sczValue); + m_pEngine->SetVariableString(pControl->sczName, sczValue); + } + } + } + } + + + + HRESULT LoadBootstrapperBAFunctions() + { + HRESULT hr = S_OK; + LPWSTR sczBafPath = NULL; + + hr = PathRelativeToModule(&sczBafPath, L"bafunctions.dll", m_hModule); + BalExitOnFailure(hr, "Failed to get path to BA function DLL."); + +#ifdef DEBUG + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXEXTBA: LoadBootstrapperBAFunctions() - BA function DLL '%ls'", sczBafPath); +#endif + + m_hBAFModule = ::LoadLibraryW(sczBafPath); + if (m_hBAFModule) + { + PFN_BOOTSTRAPPER_BA_FUNCTION_CREATE pfnBAFunctionCreate = reinterpret_cast(::GetProcAddress(m_hBAFModule, "CreateBootstrapperBAFunction")); + BalExitOnNullWithLastError1(pfnBAFunctionCreate, hr, "Failed to get CreateBootstrapperBAFunction entry-point from: %ls", sczBafPath); + + hr = pfnBAFunctionCreate(m_pEngine, m_hBAFModule, &m_pBAFunction); + BalExitOnFailure(hr, "Failed to create BA function."); + } +#ifdef DEBUG + else + { + BalLogError(HRESULT_FROM_WIN32(::GetLastError()), "WIXEXTBA: LoadBootstrapperBAFunctions() - Failed to load DLL %ls", sczBafPath); + } +#endif + +LExit: + if (m_hBAFModule && !m_pBAFunction) + { + ::FreeLibrary(m_hBAFModule); + m_hBAFModule = NULL; + } + ReleaseStr(sczBafPath); + + return hr; + } + + + #pragma comment( lib,"Wininet.lib") + + +#define BUF_LEN 1024 + +BOOL POSTRequest( + __in LPCSTR szHost, + __in LPCSTR szApiPath, + __in LPSTR szFormData, + __out LPSTR *ppszResponseMessage) +{ + BOOL bRes = false; + StrAnsiAlloc(ppszResponseMessage, BUF_LEN); + + LPCSTR header = "Content-Type: application/x-www-form-urlencoded"; + LPCSTR method = "POST"; + LPCSTR agent = "Mozilla/4.0 (compatible; MSIE 1.0)"; + + HINTERNET internet = InternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); + if(internet != NULL) + { + HINTERNET connect = InternetConnectA(internet, szHost, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0); + if(connect != NULL) + { + HINTERNET request = HttpOpenRequestA(connect, method, szApiPath, "HTTP/1.1", NULL, NULL, + INTERNET_FLAG_HYPERLINK | INTERNET_FLAG_IGNORE_CERT_CN_INVALID | + INTERNET_FLAG_IGNORE_CERT_DATE_INVALID | + INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP | + INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS | + INTERNET_FLAG_NO_AUTH | + INTERNET_FLAG_NO_CACHE_WRITE | + INTERNET_FLAG_NO_UI | + INTERNET_FLAG_PRAGMA_NOCACHE | + INTERNET_FLAG_RELOAD, NULL); + + if(request != NULL) + { + int datalen = 0; + if(szFormData != NULL) datalen = strlen(szFormData); + int headerlen = 0; + if(header != NULL) headerlen = strlen(header); + + if(HttpSendRequestA(request, header, headerlen, szFormData, datalen)) + { + // We have succesfully sent the POST request + bRes = true; + + // Now we should read the response + DWORD bytesRead; + char holdBuff[4096]; + char* temp = holdBuff; + while (InternetReadFile(request, temp, 1024, &bytesRead) == TRUE && bytesRead > 0) + { + temp += bytesRead; + } + *temp = '\0'; // manually append NULL terminator + + StringCchPrintfA(*ppszResponseMessage, BUF_LEN, holdBuff); + } + else + StringCchPrintfA(*ppszResponseMessage, BUF_LEN, "Failed to send http request."); + + InternetCloseHandle(request); + } + else + StringCchPrintfA(*ppszResponseMessage, BUF_LEN, "Failed to open http request."); + } + else + StringCchPrintfA(*ppszResponseMessage, BUF_LEN, "Connectiong to %s failed.", szHost); + + InternetCloseHandle(connect); + } + else + StringCchPrintfA(*ppszResponseMessage, BUF_LEN, "Initialize internet resources failed."); + InternetCloseHandle(internet); + + return bRes; +} + + +BOOL REST_ValidateUserLogin( + __in LPCWSTR wzUserName, + __in LPCWSTR wzPassword/*, + __out LPWSTR *ppwzErrorMessage*/ + ) +{ + BOOL bRes = false; + wchar_t wzFormData[BUF_LEN] = L""; + StringCchPrintfW(wzFormData, BUF_LEN, L"username=%s&password=%s", wzUserName, wzPassword); + + size_t i; + char *pMBFormData = (char *)malloc( BUF_LEN ); + wcstombs_s(&i, pMBFormData, (size_t)BUF_LEN, wzFormData, (size_t)BUF_LEN ); + + char *pMBDataResponse = NULL; + wchar_t wzErrorMessage[BUF_LEN] = L""; + + if (POSTRequest("accounts-stub.meteor.com", "/api/v1/login", pMBFormData, &pMBDataResponse)) + { + JSONValue *JSONResponse = JSON::Parse(pMBDataResponse); + if (JSONResponse != NULL) + { + size_t n; + + // Retrieve the main object + JSONObject JSONRoot; + if (JSONResponse->IsObject() == false) + { + mbstowcs_s(&n, wzErrorMessage, BUF_LEN, pMBDataResponse, BUF_LEN); + } + else + { + JSONRoot = JSONResponse->AsObject(); + if (JSONRoot.find(L"error") != JSONRoot.end() && JSONRoot[L"error"]->IsString()) + { + StringCchPrintfW(wzErrorMessage, BUF_LEN, JSONRoot[L"error"]->AsString().c_str()); + } + else + { + bRes = true; + + LPWSTR wzUMSFilePath = NULL; + LPWSTR wzUMSFileExpPath = NULL; + if (SUCCEEDED(BalGetStringVariable(WIXSTDBA_VARIABLE_USERMETEORSESSIONFILE, &wzUMSFilePath))) + { + if (SUCCEEDED(PathExpand(&wzUMSFileExpPath, wzUMSFilePath, PATH_EXPAND_ENVIRONMENT | PATH_EXPAND_FULLPATH))) + { + FileEnsureDelete(wzUMSFileExpPath); + HANDLE hFile = CreateFileW(wzUMSFileExpPath, GENERIC_ALL, 0, 0L, 1, 0x80L, 0); + if (hFile != INVALID_HANDLE_VALUE) + { + DWORD bytesWritten; + WriteFile(hFile, pMBDataResponse, strlen(pMBDataResponse), &bytesWritten, NULL); + CloseHandle( hFile); + } + } + } + } + } + } + else + wcsncat_s(wzErrorMessage, L"Unknown error.", BUF_LEN-1); + + // Clean up JSON object + delete JSONResponse; + } + + + if (bRes == false) + { + wchar_t wzMessage[BUF_LEN] = L""; + StringCchPrintfW(wzMessage, BUF_LEN, L"Setup was unable to check your account. %s", wzErrorMessage); + MessageBoxW(m_hWnd, wzMessage, m_pTheme->sczCaption, MB_ICONEXCLAMATION | MB_OK); + } + + return bRes; +} + + + HRESULT DAPI LocGetString( + __in const WIX_LOCALIZATION* pWixLoc, + __in_z LPCWSTR wzId, + __out LOC_STRING** ppLocString + ) + { + HRESULT hr = E_NOTFOUND; + LOC_STRING* pLocString = NULL; + + for (DWORD i = 0; i < pWixLoc->cLocStrings; ++i) + { + pLocString = pWixLoc->rgLocStrings + i; + + if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pLocString->wzId, -1, wzId, -1)) + { + *ppLocString = pLocString; + hr = S_OK; + break; + } + } + + return hr; + } +public: + // + // Constructor - intitialize member variables. + // + CWixStandardBootstrapperApplication( + __in HMODULE hModule, + __in BOOL fPrereq, + __in IBootstrapperEngine* pEngine, + __in const BOOTSTRAPPER_COMMAND* pCommand + ) : CBalBaseBootstrapperApplication(pEngine, pCommand, 3, 3000) + { + m_hModule = hModule; + memcpy_s(&m_command, sizeof(m_command), pCommand, sizeof(BOOTSTRAPPER_COMMAND)); + + // Pre-req BA should only show help or do an install (to launch the Managed BA which can then do the right action). + if (fPrereq && BOOTSTRAPPER_ACTION_HELP != m_command.action && BOOTSTRAPPER_ACTION_INSTALL != m_command.action) + { + m_command.action = BOOTSTRAPPER_ACTION_INSTALL; + } + else // maybe modify the action state if the bundle is or is not already installed. + { + LONGLONG llInstalled = 0; + HRESULT hr = BalGetNumericVariable(L"WixBundleInstalled", &llInstalled); + if (SUCCEEDED(hr) && BOOTSTRAPPER_RESUME_TYPE_REBOOT != m_command.resumeType && 0 < llInstalled && BOOTSTRAPPER_ACTION_INSTALL == m_command.action) + { + m_command.action = BOOTSTRAPPER_ACTION_MODIFY; + } + else if (0 == llInstalled && (BOOTSTRAPPER_ACTION_MODIFY == m_command.action || BOOTSTRAPPER_ACTION_REPAIR == m_command.action)) + { + m_command.action = BOOTSTRAPPER_ACTION_INSTALL; + } + } + + m_plannedAction = BOOTSTRAPPER_ACTION_UNKNOWN; + + // When resuming from restart doing some install-like operation, try to find the package that forced the + // restart. We'll use this information during planning. + m_sczAfterForcedRestartPackage = NULL; + + if (BOOTSTRAPPER_RESUME_TYPE_REBOOT == m_command.resumeType && BOOTSTRAPPER_ACTION_UNINSTALL < m_command.action) + { + // Ensure the forced restart package variable is null when it is an empty string. + HRESULT hr = BalGetStringVariable(L"WixBundleForcedRestartPackage", &m_sczAfterForcedRestartPackage); + if (FAILED(hr) || !m_sczAfterForcedRestartPackage || !*m_sczAfterForcedRestartPackage) + { + ReleaseNullStr(m_sczAfterForcedRestartPackage); + } + } + + m_pWixLoc = NULL; + memset(&m_Bundle, 0, sizeof(m_Bundle)); + memset(&m_Conditions, 0, sizeof(m_Conditions)); + m_sczConfirmCloseMessage = NULL; + m_sczFailedMessage = NULL; + + m_sczLanguage = NULL; + m_pTheme = NULL; + memset(m_rgdwPageIds, 0, sizeof(m_rgdwPageIds)); + m_dwCurrentPage = 0; + m_hUiThread = NULL; + m_fRegistered = FALSE; + m_hWnd = NULL; + + m_state = WIXSTDBA_STATE_INITIALIZING; + m_hrFinal = S_OK; + + m_fDowngrading = FALSE; + m_restartResult = BOOTSTRAPPER_APPLY_RESTART_NONE; + m_fRestartRequired = FALSE; + m_fAllowRestart = FALSE; + + m_sczLicenseFile = NULL; + m_sczLicenseUrl = NULL; + m_fSuppressOptionsUI = FALSE; + m_fSuppressDowngradeFailure = FALSE; + m_fSuppressRepair = FALSE; + m_fShowVersion = FALSE; + m_fIsRepair = FALSE; + m_fIsUninstall = FALSE; + m_fInstallSucceed = FALSE; + m_fIsProductCore = FALSE; + m_sdOverridableVariables = NULL; + m_pTaskbarList = NULL; + m_uTaskbarButtonCreatedMessage = UINT_MAX; + m_fTaskbarButtonOK = FALSE; + m_fShowingInternalUiThisPackage = FALSE; + + m_fPrereq = fPrereq; + m_sczPrereqPackage = NULL; + m_fPrereqInstalled = FALSE; + m_fPrereqAlreadyInstalled = FALSE; + m_fOverallInstallationStarted = FALSE; + m_fUpdating = FALSE; + + pEngine->AddRef(); + m_pEngine = pEngine; + + m_hBAFModule = NULL; + m_pBAFunction = NULL; + } + + + // + // Destructor - release member variables. + // + ~CWixStandardBootstrapperApplication() + { + CopyBundleLogToSpecifiedPath(); + AssertSz(!::IsWindow(m_hWnd), "Window should have been destroyed before destructor."); + AssertSz(!m_pTheme, "Theme should have been released before destuctor."); + + ReleaseObject(m_pTaskbarList); + ReleaseDict(m_sdOverridableVariables); + ReleaseStr(m_sczFailedMessage); + ReleaseStr(m_sczConfirmCloseMessage); + BalConditionsUninitialize(&m_Conditions); + BalInfoUninitialize(&m_Bundle); + LocFree(m_pWixLoc); + + ReleaseStr(m_sczLanguage); + ReleaseStr(m_sczLicenseFile); + ReleaseStr(m_sczLicenseUrl); + ReleaseStr(m_sczPrereqPackage); + ReleaseStr(m_sczAfterForcedRestartPackage); + ReleaseNullObject(m_pEngine); + + if (m_hBAFModule) + { + ::FreeLibrary(m_hBAFModule); + m_hBAFModule = NULL; + } + } + +private: + HMODULE m_hModule; + BOOTSTRAPPER_COMMAND m_command; + IBootstrapperEngine* m_pEngine; + BOOTSTRAPPER_ACTION m_plannedAction; + + LPWSTR m_sczAfterForcedRestartPackage; + + WIX_LOCALIZATION* m_pWixLoc; + BAL_INFO_BUNDLE m_Bundle; + BAL_CONDITIONS m_Conditions; + LPWSTR m_sczFailedMessage; + LPWSTR m_sczConfirmCloseMessage; + + LPWSTR m_sczLanguage; + THEME* m_pTheme; + DWORD m_rgdwPageIds[countof(vrgwzPageNames)]; + DWORD m_dwCurrentPage; + HANDLE m_hUiThread; + BOOL m_fRegistered; + HWND m_hWnd; + + WIXSTDBA_STATE m_state; + WIXSTDBA_STATE m_stateInstallPage; + HRESULT m_hrFinal; + + BOOL m_fStartedExecution; + DWORD m_dwCalculatedCacheProgress; + DWORD m_dwCalculatedExecuteProgress; + + BOOL m_fDowngrading; + BOOTSTRAPPER_APPLY_RESTART m_restartResult; + BOOL m_fRestartRequired; + BOOL m_fAllowRestart; + + LPWSTR m_sczLicenseFile; + LPWSTR m_sczLicenseUrl; + BOOL m_fSuppressOptionsUI; + BOOL m_fSuppressDowngradeFailure; + BOOL m_fSuppressRepair; + BOOL m_fShowVersion; + BOOL m_fIsRepair; + BOOL m_fIsUninstall; + BOOL m_fInstallSucceed; + + BOOTSTRAPPER_RELATED_OPERATION m_Operation; + + BOOL m_fIsProductCore; + BOOL m_fOverallInstallationStarted; + + + STRINGDICT_HANDLE m_sdOverridableVariables; + + BOOL m_fPrereq; + LPWSTR m_sczPrereqPackage; + BOOL m_fPrereqInstalled; + BOOL m_fPrereqAlreadyInstalled; + + ITaskbarList3* m_pTaskbarList; + UINT m_uTaskbarButtonCreatedMessage; + BOOL m_fTaskbarButtonOK; + BOOL m_fShowingInternalUiThisPackage; + + BOOL m_fUpdating; + LPCWSTR m_wzUpdateLocation; + + HMODULE m_hBAFModule; + IBootstrapperBAFunction* m_pBAFunction; +}; + + +// +// CreateUserExperience - creates a new IBurnUserExperience object. +// +HRESULT CreateBootstrapperApplication( + __in HMODULE hModule, + __in BOOL fPrereq, + __in IBootstrapperEngine* pEngine, + __in const BOOTSTRAPPER_COMMAND* pCommand, + __out IBootstrapperApplication** ppApplication + ) +{ + HRESULT hr = S_OK; + CWixStandardBootstrapperApplication* pApplication = NULL; + + pApplication = new CWixStandardBootstrapperApplication(hModule, fPrereq, pEngine, pCommand); + ExitOnNull(pApplication, hr, E_OUTOFMEMORY, "Failed to create new standard bootstrapper application object."); + + *ppApplication = pApplication; + pApplication = NULL; + +LExit: + ReleaseObject(pApplication); + return hr; +} diff --git a/scripts/windows/wix-installer/WiXBalExtension/wixstdba/wixstdba.vcxproj b/scripts/windows/wix-installer/WiXBalExtension/wixstdba/wixstdba.vcxproj index 3c38271c60..55553440c0 100755 --- a/scripts/windows/wix-installer/WiXBalExtension/wixstdba/wixstdba.vcxproj +++ b/scripts/windows/wix-installer/WiXBalExtension/wixstdba/wixstdba.vcxproj @@ -1,4 +1,4 @@ - + - - - - Debug - Win32 - - - Release - Win32 - - - - {41085a22-e6aa-4e8b-ab1b-ddee0dc89dfa} - WixStdBA - Win32Proj - DynamicLibrary - MultiByte - wixextba - - - - v100 - - - v100 - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(Configuration)\ - $(Configuration)\ - true - AllRules.ruleset - - - $(Configuration)\ - $(Configuration)\ - true - AllRules.ruleset - - - - - - - - - - Disabled - $(WiX)SDK\inc;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;DEBUG;%(PreprocessorDefinitions);$(ExtraDefinitions) - true - EnableFastChecks - MultiThreadedDebug - NotUsing - precomp.h - $(IntDir)$(ProjectName).pdb - Level4 - ProgramDatabase - StdCall - true - 4995 - - - $(ProjectDir)..\inc;%(AdditionalIncludeDirectories) - - - dutil.lib;balutil.lib;comctl32.lib;msimg32.lib;gdiplus.lib;shlwapi.lib;wininet.lib;version.lib;%(AdditionalDependencies) - ..\..\WiXSDK\VS2010\lib\x86;%(AdditionalLibraryDirectories) - wixstdba.def - true - Windows - - - - - - - - - Disabled - ..\..\WiXSDK\inc;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);$(ExtraDefinitions) - true - EnableFastChecks - MultiThreaded - NotUsing - precomp.h - $(IntDir)$(ProjectName).pdb - Level4 - ProgramDatabase - StdCall - true - 4995 - - - $(ProjectDir)..\inc;%(AdditionalIncludeDirectories) - - - dutil.lib;balutil.lib;comctl32.lib;msimg32.lib;gdiplus.lib;shlwapi.lib;wininet.lib;version.lib;%(AdditionalDependencies) - ..\..\WiXSDK\VS2010\lib\x86;%(AdditionalLibraryDirectories) - wixstdba.def - false - Windows - - - - - - - - Create - Create - - - - - - - - - - Designer - - - - - - - - - - - - - - - +--> + + + + Debug + Win32 + + + Release + Win32 + + + + {41085a22-e6aa-4e8b-ab1b-ddee0dc89dfa} + WixStdBA + Win32Proj + DynamicLibrary + MultiByte + wixextba + + + + v100 + + + v100 + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(Configuration)\ + $(Configuration)\ + true + AllRules.ruleset + + + $(Configuration)\ + $(Configuration)\ + true + AllRules.ruleset + + + + + + + + + + Disabled + $(WiX)SDK\inc;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;DEBUG;%(PreprocessorDefinitions);$(ExtraDefinitions) + true + EnableFastChecks + MultiThreadedDebug + NotUsing + precomp.h + $(IntDir)$(ProjectName).pdb + Level4 + ProgramDatabase + StdCall + true + 4995 + + + $(ProjectDir)..\inc;%(AdditionalIncludeDirectories) + + + dutil.lib;balutil.lib;comctl32.lib;msimg32.lib;gdiplus.lib;shlwapi.lib;wininet.lib;version.lib;%(AdditionalDependencies) + ..\..\WiXSDK\VS2010\lib\x86;%(AdditionalLibraryDirectories) + wixstdba.def + true + Windows + + + + + + + + + Disabled + ..\..\WiXSDK\inc;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);$(ExtraDefinitions) + true + EnableFastChecks + MultiThreaded + NotUsing + precomp.h + $(IntDir)$(ProjectName).pdb + Level4 + ProgramDatabase + StdCall + true + 4995 + + + $(ProjectDir)..\inc;%(AdditionalIncludeDirectories) + + + dutil.lib;balutil.lib;comctl32.lib;msimg32.lib;gdiplus.lib;shlwapi.lib;wininet.lib;version.lib;%(AdditionalDependencies) + ..\..\WiXSDK\VS2010\lib\x86;%(AdditionalLibraryDirectories) + wixstdba.def + false + Windows + + + + + + + + Create + Create + + + + + + + + + + Designer + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/scripts/windows/wix-installer/WiXBalExtension/wixstdba/wixstdba.vcxproj.filters b/scripts/windows/wix-installer/WiXBalExtension/wixstdba/wixstdba.vcxproj.filters index 23f03c0b71..405b4233fb 100755 --- a/scripts/windows/wix-installer/WiXBalExtension/wixstdba/wixstdba.vcxproj.filters +++ b/scripts/windows/wix-installer/WiXBalExtension/wixstdba/wixstdba.vcxproj.filters @@ -1,73 +1,73 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Source Files - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Resource Files - - + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Source Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Resource Files + + \ No newline at end of file diff --git a/scripts/windows/wix-installer/WiXHelper/.gitignore b/scripts/windows/wix-installer/WiXHelper/.gitignore new file mode 100644 index 0000000000..57a1574c4f --- /dev/null +++ b/scripts/windows/wix-installer/WiXHelper/.gitignore @@ -0,0 +1,196 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Visual Studo 2015 cache/options directory +.vs/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding addin-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +*.[Cc]ache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt diff --git a/scripts/windows/wix-installer/WiXHelper/CustomAction.cpp b/scripts/windows/wix-installer/WiXHelper/CustomAction.cpp index af62dfae34..c86bc27909 100755 --- a/scripts/windows/wix-installer/WiXHelper/CustomAction.cpp +++ b/scripts/windows/wix-installer/WiXHelper/CustomAction.cpp @@ -1,447 +1,447 @@ -#include "stdafx.h" - - -#include - -#include -#include - -#include -#include -#include - -#include -#include -#include - -#define BUF_LEN 1024 -#define MAX_LONG_PATH 2048 -#define LOG true - - - - - - - - -using namespace std; - -class MyCallback : public IBindStatusCallback -{ -public: - MSIHANDLE iHInstall; - MyCallback() {} - - ~MyCallback() { } - - // This one is called by URLDownloadToFile - STDMETHOD(OnProgress)(/* [in] */ ULONG ulProgress, /* [in] */ ULONG ulProgressMax, /* [in] */ ULONG ulStatusCode, /* [in] */ LPCWSTR wszStatusText) - { - PMSIHANDLE hActionRec = MsiCreateRecord(3); - PMSIHANDLE hProgressRec = MsiCreateRecord(3); - - DWORD ulPrc = 0; - WCHAR wzInfo[1024] = { }; - - if (ulProgressMax > 0) - { - ulPrc = static_cast(100 * static_cast(ulProgress) / static_cast(ulProgressMax)); - ::StringCchPrintfW(wzInfo, countof(wzInfo), L"Downloading Meteor package ... %u%%", ulPrc); - } - else - ::StringCchPrintfW(wzInfo, countof(wzInfo), L"Downloading Meteor package ..."); - - - - MsiRecordSetString(hActionRec, 1, TEXT("Download_MeteorPackage")); - MsiRecordSetString(hActionRec, 2, wzInfo); - MsiRecordSetString(hActionRec, 3, NULL); - UINT iResult = MsiProcessMessage(iHInstall, INSTALLMESSAGE_ACTIONSTART, hActionRec); - if ((iResult == IDCANCEL) || (iResult == IDABORT)) - return E_ABORT; - - return S_OK; - } - - // The rest don't do anything... - STDMETHOD(OnStartBinding)(/* [in] */ DWORD dwReserved, /* [in] */ IBinding __RPC_FAR *pib) - { return E_NOTIMPL; } - - STDMETHOD(GetPriority)(/* [out] */ LONG __RPC_FAR *pnPriority) - { return E_NOTIMPL; } - - STDMETHOD(OnLowResource)(/* [in] */ DWORD reserved) - { return E_NOTIMPL; } - - STDMETHOD(OnStopBinding)(/* [in] */ HRESULT hresult, /* [unique][in] */ LPCWSTR szError) - { return E_NOTIMPL; } - - STDMETHOD(GetBindInfo)(/* [out] */ DWORD __RPC_FAR *grfBINDF, /* [unique][out][in] */ BINDINFO __RPC_FAR *pbindinfo) - { return E_NOTIMPL; } - - STDMETHOD(OnDataAvailable)(/* [in] */ DWORD grfBSCF, /* [in] */ DWORD dwSize, /* [in] */ FORMATETC __RPC_FAR *pformatetc, /* [in] */ STGMEDIUM __RPC_FAR *pstgmed) - { return E_NOTIMPL; } - - STDMETHOD(OnObjectAvailable)(/* [in] */ REFIID riid, /* [iid_is][in] */ IUnknown __RPC_FAR *punk) - { return E_NOTIMPL; } - - // IUnknown stuff - STDMETHOD_(ULONG,AddRef)() - { return 0; } - - STDMETHOD_(ULONG,Release)() - { return 0; } - - STDMETHOD(QueryInterface)(/* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject) - { return E_NOTIMPL; } -}; - - - - - -HRESULT ExtractBinary( - __in LPCWSTR wzBinaryId, - __out BYTE** pbData, - __out DWORD* pcbData - ) -{ - HRESULT hr = S_OK; - LPWSTR pwzSql = NULL; - PMSIHANDLE hView; - PMSIHANDLE hRec; - - // make sure we're not horked from the get-go - hr = WcaTableExists(L"Binary"); - if (S_OK != hr) - { - if (SUCCEEDED(hr)) - { - hr = E_UNEXPECTED; - } - ExitOnFailure(hr, "There is no Binary table."); - } - - ExitOnNull(wzBinaryId, hr, E_INVALIDARG, "Binary ID cannot be null"); - ExitOnNull(*wzBinaryId, hr, E_INVALIDARG, "Binary ID cannot be empty string"); - - hr = StrAllocFormatted(&pwzSql, L"SELECT `Data` FROM `Binary` WHERE `Name`=\'%s\'", wzBinaryId); - ExitOnFailure(hr, "Failed to allocate Binary table query."); - - hr = WcaOpenExecuteView(pwzSql, &hView); - ExitOnFailure(hr, "Failed to open view on Binary table"); - - hr = WcaFetchSingleRecord(hView, &hRec); - ExitOnFailure(hr, "Failed to retrieve request from Binary table"); - - hr = WcaGetRecordStream(hRec, 1, pbData, pcbData); - ExitOnFailure(hr, "Failed to read Binary.Data."); - -LExit: - ReleaseStr(pwzSql); - return hr; -} - - -HRESULT ExtractBinaryToFile( - __in LPCWSTR wzBinaryId, - __in LPCWSTR wzFilePath - ) -{ - HRESULT hr = S_OK; - BYTE* pbData = NULL; - DWORD cbData = 0; - DWORD cbWritten = 0; - - HANDLE hFile = INVALID_HANDLE_VALUE; - - wchar_t szTmpFile[BUF_LEN] = L""; DWORD nTmpFileLen = BUF_LEN; - hr = ExtractBinary(wzBinaryId, &pbData, &cbData); - - hFile = CreateFile(wzFilePath, GENERIC_WRITE,FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile != INVALID_HANDLE_VALUE) { - WriteFile(hFile, pbData, cbData, &cbWritten, NULL); - CloseHandle(hFile); - } - else - { - hr = HRESULT_FROM_WIN32(::GetLastError()); - } - - return hr; -} - - - - -BOOL ExecuteCommandLine(LPWSTR CommandLine, DWORD & exitCode) -{ - PROCESS_INFORMATION processInformation = {0}; - STARTUPINFO startupInfo = {0}; - startupInfo.cb = sizeof(startupInfo); - - // Create the process - BOOL result = CreateProcess(NULL, CommandLine, - NULL, NULL, FALSE, - NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, - NULL, NULL, &startupInfo, &processInformation); - - if (!result) - { - // CreateProcess() failed; Get the error from the system - LPVOID lpMsgBuf; - DWORD dw = GetLastError(); - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL); - - // Display the error - LPTSTR strError = (LPTSTR) lpMsgBuf; - - // Free resources created by the system - LocalFree(lpMsgBuf); - - // We failed. - return FALSE; - } - else - { - // Successfully created the process. Wait for it to finish. - WaitForSingleObject( processInformation.hProcess, INFINITE ); - - // Get the exit code. - result = GetExitCodeProcess(processInformation.hProcess, &exitCode); - - // Close the handles. - CloseHandle( processInformation.hProcess ); - CloseHandle( processInformation.hThread ); - - if (!result) - return FALSE; - - // We succeeded. - return TRUE; - } -} - - -HRESULT UnzipToFolder( - MSIHANDLE hInstall, - __in LPCWSTR wzFriendlyName, - __in LPCWSTR wzTarGzFileName, - __in LPCWSTR wzDestPath - ) -{ - HRESULT hr = S_OK; - - WcaLog(LOGMSG_STANDARD, "Extract \"%S\" package initialized.", wzFriendlyName); - - wchar_t szSourceDir[BUF_LEN] = L""; DWORD nSourceDirDirLen = BUF_LEN; - wchar_t szTarGzFilePath[BUF_LEN] = L""; - wchar_t szTarFilePath[BUF_LEN] = L""; - MsiGetProperty(hInstall, L"SourceDir", szSourceDir, &nSourceDirDirLen); - StringCchPrintf(szTarGzFilePath, BUF_LEN, L"%s%s", szSourceDir, wzTarGzFileName); - StringCchPrintf(szTarFilePath, BUF_LEN, L"%s*.tar", szSourceDir); - - DWORD pdwAttr; - if (FileExistsEx(szTarGzFilePath, &pdwAttr) == TRUE) - { - //Extacting quality_cloud_production.sql to %TEMP% folder - wchar_t szTmpDir[BUF_LEN] = L""; DWORD nTmpDirLen = BUF_LEN; - wchar_t sz7Zip[BUF_LEN] = L""; - - wchar_t szCommandLine1[BUF_LEN] = L""; - wchar_t szCommandLine2[BUF_LEN] = L""; - - MsiGetProperty(hInstall, L"TempFolder", szTmpDir, &nTmpDirLen); - StringCchPrintf(sz7Zip, BUF_LEN, L"%s%s", szTmpDir, L"7za.exe"); - - DWORD pdwAttr; - if (FileExistsEx(sz7Zip, &pdwAttr) == FALSE) - { - hr = ExtractBinaryToFile(L"SevenZip", sz7Zip); - } - - StringCchPrintf(szCommandLine1, BUF_LEN, L"\"%s\" x -o\"%s\" -y \"%s\"", sz7Zip, szSourceDir, szTarGzFilePath); - StringCchPrintf(szCommandLine2, BUF_LEN, L"\"%s\" x -o\"%s\" -y \"%s\"", sz7Zip, wzDestPath, szTarFilePath); - DWORD nRes=0; - LPTSTR ErrorMessage = NULL; - - ExecuteCommandLine(szCommandLine1, nRes); - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, HRESULT_FROM_WIN32(nRes), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&ErrorMessage, 0, NULL); - if (NULL != ErrorMessage) WcaLog(LOGMSG_STANDARD, "Archive expanding completed with (%d): %S", nRes, ErrorMessage); - - ExecuteCommandLine(szCommandLine2, nRes); - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, HRESULT_FROM_WIN32(nRes), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&ErrorMessage, 0, NULL); - if (NULL != ErrorMessage) WcaLog(LOGMSG_STANDARD, "Archive deployment completed with (%d): %S", nRes, ErrorMessage); - } - else - { - hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); - WcaLog(LOGMSG_STANDARD, "Failed to extract %S files. File not found: %S", wzFriendlyName, szTarGzFilePath); - } - - WcaLog(LOGMSG_STANDARD, "Extracting \"%S\" package completed.", wzFriendlyName); - - return hr; -} - - -UINT __stdcall Extract_MeteorFiles(MSIHANDLE hInstall) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - hr = WcaInitialize(hInstall, "Extract_MeteorFiles"); - ExitOnFailure(hr, "Failed to initialize Extract_MeteorFiles"); - - wchar_t szMeteorDir[BUF_LEN] = L""; DWORD nMeteorDirLen = BUF_LEN; - MsiGetProperty(hInstall, L"METEOR_DIR", szMeteorDir, &nMeteorDirLen); - - hr = UnzipToFolder(hInstall, L"Meteor", L"meteor-bootstrap-os.windows.x86_32.tar.gz", szMeteorDir); - ExitOnFailure(hr, "Failed to extract Meteor files."); - -LExit: - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - - - -HRESULT Download_Package( - MSIHANDLE hInstall, - __in LPCWSTR wzFriendlyName, - __in LPCWSTR wzProperty_DWNURL, - __in LPCWSTR wzZipFile) -{ - HRESULT hr = S_OK; - - WcaLog(LOGMSG_STANDARD, "Download package \"%S\" initialized.", wzFriendlyName); - - wchar_t szSourceDir[BUF_LEN] = L""; DWORD nSourceDirDirLen = BUF_LEN; - wchar_t szDwnUrl[BUF_LEN] = L""; DWORD nDwnUrlLen = BUF_LEN; - wchar_t szDwnUser[BUF_LEN] = L""; DWORD nDwnUserLen = BUF_LEN; - wchar_t szDwnPass[BUF_LEN] = L""; DWORD nDwnPassLen = BUF_LEN; - wchar_t szZipFile[BUF_LEN] = L""; - - MsiGetProperty(hInstall, L"SourceDir", szSourceDir, &nSourceDirDirLen); - MsiGetProperty(hInstall, wzProperty_DWNURL, szDwnUrl, &nDwnUrlLen); - MsiGetProperty(hInstall, L"HTTP_DWN_USER", szDwnUser, &nDwnUserLen); - MsiGetProperty(hInstall, L"HTTP_DWN_PASS", szDwnPass, &nDwnPassLen); - StringCchPrintf(szZipFile, BUF_LEN, L"%s%s", szSourceDir, wzZipFile); - - // Checking for Prerequisites\localFile - wchar_t szBundleSrc[BUF_LEN] = L""; DWORD nBundleSrcLen = BUF_LEN; - wchar_t szPrereqDir[BUF_LEN] = L""; DWORD nPrereqDirLen = BUF_LEN; - wchar_t szLocalFile[BUF_LEN] = L""; - wchar_t* szBundlePath; - MsiGetProperty(hInstall, L"BUNDLE_SOURCE", szBundleSrc, &nBundleSrcLen); - MsiGetProperty(hInstall, L"PREREQ_FOLDER", szPrereqDir, &nPrereqDirLen); - PathGetDirectory(szBundleSrc, &szBundlePath); - StringCchPrintf(szLocalFile, BUF_LEN, L"%s%s\\%s", szBundlePath, szPrereqDir, wzZipFile); - - // If local file exists use it instaead of download. - DWORD pdwAttr; - if (FileExistsEx(szLocalFile, &pdwAttr) == TRUE) - { - FileEnsureCopy(szLocalFile, szZipFile, TRUE); - WcaLog(LOGMSG_STANDARD, "Nginx local package found \"%S\", will use that.", szLocalFile); - } - else - { - MyCallback pCallback; - pCallback.iHInstall = hInstall; - hr = URLDownloadToFile(NULL, szDwnUrl, szZipFile, 0, &pCallback); - - if (FAILED(hr)) - WcaLog(LOGMSG_STANDARD, "Failed to download %S package from url: %S", wzFriendlyName, szDwnUrl); - else - WcaLog(LOGMSG_STANDARD, "%S package should be here: %S", wzFriendlyName, szZipFile); - } - - WcaLog(LOGMSG_STANDARD, "Download package \"%S\" completed.", wzFriendlyName); - - return hr; -} - - - -UINT __stdcall Download_MeteorPackage(MSIHANDLE hInstall) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - hr = WcaInitialize(hInstall, "Download_MeteorPackage"); - ExitOnFailure(hr, "Failed to initialize Download_MeteorPackage"); - - hr = Download_Package(hInstall, L"Meteor", L"METEOR_DWN_URL", L"meteor-bootstrap-os.windows.x86_32.tar.gz"); - ExitOnFailure(hr, "Failed to download Meteor package from specified URL."); - -LExit: - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - - - - -UINT __stdcall BulkRemoveMeteorFiles(MSIHANDLE hInstall) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - hr = WcaInitialize(hInstall, "BulkRemoveMeteorFiles"); - ExitOnFailure(hr, "Failed to initialize BulkRemoveMeteorFiles"); - - WcaLog(LOGMSG_STANDARD, "BulkRemoveMeteorFiles Initialized."); - - wchar_t szPathPackages[BUF_LEN] = L""; DWORD nPathPackages = BUF_LEN; - wchar_t szPathPkg_Meta[BUF_LEN] = L""; DWORD nPathPkg_Meta = BUF_LEN; - - MsiGetProperty(hInstall, L"METEORDIR_PACKAGES", szPathPackages, &nPathPackages); - MsiGetProperty(hInstall, L"METEORDIR_PKG_META", szPathPkg_Meta, &nPathPkg_Meta); - - wchar_t szSysDir[BUF_LEN] = L""; DWORD nSysDirLen = BUF_LEN; - wchar_t szCmd1[BUF_LEN] = L""; - wchar_t szCmd2[BUF_LEN] = L""; - - DWORD nRes=0; - - - MsiGetProperty(hInstall, L"SystemFolder", szSysDir, &nSysDirLen); - StringCchPrintf(szCmd1, BUF_LEN, L"%s\\cmd.exe /C \"RD /S /Q \"%s\">NUL\"", szSysDir, szPathPackages); - StringCchPrintf(szCmd2, BUF_LEN, L"%s\\cmd.exe /C \"RD /S /Q \"%s\">NUL\"", szSysDir, szPathPkg_Meta); - - ExecuteCommandLine(szCmd1, nRes); - ExecuteCommandLine(szCmd2, nRes); - - WcaLog(LOGMSG_STANDARD, "BulkRemoveMeteorFiles done."); - -LExit: - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - - - - -// DllMain - Initialize and cleanup WiX custom action utils. -extern "C" BOOL WINAPI DllMain( - __in HINSTANCE hInst, - __in ULONG ulReason, - __in LPVOID - ) -{ - switch(ulReason) - { - case DLL_PROCESS_ATTACH: - WcaGlobalInitialize(hInst); - break; - - case DLL_PROCESS_DETACH: - WcaGlobalFinalize(); - break; - } - - return TRUE; -} +#include "stdafx.h" + + +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#define BUF_LEN 1024 +#define MAX_LONG_PATH 2048 +#define LOG true + + + + + + + + +using namespace std; + +class MyCallback : public IBindStatusCallback +{ +public: + MSIHANDLE iHInstall; + MyCallback() {} + + ~MyCallback() { } + + // This one is called by URLDownloadToFile + STDMETHOD(OnProgress)(/* [in] */ ULONG ulProgress, /* [in] */ ULONG ulProgressMax, /* [in] */ ULONG ulStatusCode, /* [in] */ LPCWSTR wszStatusText) + { + PMSIHANDLE hActionRec = MsiCreateRecord(3); + PMSIHANDLE hProgressRec = MsiCreateRecord(3); + + DWORD ulPrc = 0; + WCHAR wzInfo[1024] = { }; + + if (ulProgressMax > 0) + { + ulPrc = static_cast(100 * static_cast(ulProgress) / static_cast(ulProgressMax)); + ::StringCchPrintfW(wzInfo, countof(wzInfo), L"Downloading Meteor package ... %u%%", ulPrc); + } + else + ::StringCchPrintfW(wzInfo, countof(wzInfo), L"Downloading Meteor package ..."); + + + + MsiRecordSetString(hActionRec, 1, TEXT("Download_MeteorPackage")); + MsiRecordSetString(hActionRec, 2, wzInfo); + MsiRecordSetString(hActionRec, 3, NULL); + UINT iResult = MsiProcessMessage(iHInstall, INSTALLMESSAGE_ACTIONSTART, hActionRec); + if ((iResult == IDCANCEL) || (iResult == IDABORT)) + return E_ABORT; + + return S_OK; + } + + // The rest don't do anything... + STDMETHOD(OnStartBinding)(/* [in] */ DWORD dwReserved, /* [in] */ IBinding __RPC_FAR *pib) + { return E_NOTIMPL; } + + STDMETHOD(GetPriority)(/* [out] */ LONG __RPC_FAR *pnPriority) + { return E_NOTIMPL; } + + STDMETHOD(OnLowResource)(/* [in] */ DWORD reserved) + { return E_NOTIMPL; } + + STDMETHOD(OnStopBinding)(/* [in] */ HRESULT hresult, /* [unique][in] */ LPCWSTR szError) + { return E_NOTIMPL; } + + STDMETHOD(GetBindInfo)(/* [out] */ DWORD __RPC_FAR *grfBINDF, /* [unique][out][in] */ BINDINFO __RPC_FAR *pbindinfo) + { return E_NOTIMPL; } + + STDMETHOD(OnDataAvailable)(/* [in] */ DWORD grfBSCF, /* [in] */ DWORD dwSize, /* [in] */ FORMATETC __RPC_FAR *pformatetc, /* [in] */ STGMEDIUM __RPC_FAR *pstgmed) + { return E_NOTIMPL; } + + STDMETHOD(OnObjectAvailable)(/* [in] */ REFIID riid, /* [iid_is][in] */ IUnknown __RPC_FAR *punk) + { return E_NOTIMPL; } + + // IUnknown stuff + STDMETHOD_(ULONG,AddRef)() + { return 0; } + + STDMETHOD_(ULONG,Release)() + { return 0; } + + STDMETHOD(QueryInterface)(/* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject) + { return E_NOTIMPL; } +}; + + + + + +HRESULT ExtractBinary( + __in LPCWSTR wzBinaryId, + __out BYTE** pbData, + __out DWORD* pcbData + ) +{ + HRESULT hr = S_OK; + LPWSTR pwzSql = NULL; + PMSIHANDLE hView; + PMSIHANDLE hRec; + + // make sure we're not horked from the get-go + hr = WcaTableExists(L"Binary"); + if (S_OK != hr) + { + if (SUCCEEDED(hr)) + { + hr = E_UNEXPECTED; + } + ExitOnFailure(hr, "There is no Binary table."); + } + + ExitOnNull(wzBinaryId, hr, E_INVALIDARG, "Binary ID cannot be null"); + ExitOnNull(*wzBinaryId, hr, E_INVALIDARG, "Binary ID cannot be empty string"); + + hr = StrAllocFormatted(&pwzSql, L"SELECT `Data` FROM `Binary` WHERE `Name`=\'%s\'", wzBinaryId); + ExitOnFailure(hr, "Failed to allocate Binary table query."); + + hr = WcaOpenExecuteView(pwzSql, &hView); + ExitOnFailure(hr, "Failed to open view on Binary table"); + + hr = WcaFetchSingleRecord(hView, &hRec); + ExitOnFailure(hr, "Failed to retrieve request from Binary table"); + + hr = WcaGetRecordStream(hRec, 1, pbData, pcbData); + ExitOnFailure(hr, "Failed to read Binary.Data."); + +LExit: + ReleaseStr(pwzSql); + return hr; +} + + +HRESULT ExtractBinaryToFile( + __in LPCWSTR wzBinaryId, + __in LPCWSTR wzFilePath + ) +{ + HRESULT hr = S_OK; + BYTE* pbData = NULL; + DWORD cbData = 0; + DWORD cbWritten = 0; + + HANDLE hFile = INVALID_HANDLE_VALUE; + + wchar_t szTmpFile[BUF_LEN] = L""; DWORD nTmpFileLen = BUF_LEN; + hr = ExtractBinary(wzBinaryId, &pbData, &cbData); + + hFile = CreateFile(wzFilePath, GENERIC_WRITE,FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile != INVALID_HANDLE_VALUE) { + WriteFile(hFile, pbData, cbData, &cbWritten, NULL); + CloseHandle(hFile); + } + else + { + hr = HRESULT_FROM_WIN32(::GetLastError()); + } + + return hr; +} + + + + +BOOL ExecuteCommandLine(LPWSTR CommandLine, DWORD & exitCode) +{ + PROCESS_INFORMATION processInformation = {0}; + STARTUPINFO startupInfo = {0}; + startupInfo.cb = sizeof(startupInfo); + + // Create the process + BOOL result = CreateProcess(NULL, CommandLine, + NULL, NULL, FALSE, + NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, + NULL, NULL, &startupInfo, &processInformation); + + if (!result) + { + // CreateProcess() failed; Get the error from the system + LPVOID lpMsgBuf; + DWORD dw = GetLastError(); + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL); + + // Display the error + LPTSTR strError = (LPTSTR) lpMsgBuf; + + // Free resources created by the system + LocalFree(lpMsgBuf); + + // We failed. + return FALSE; + } + else + { + // Successfully created the process. Wait for it to finish. + WaitForSingleObject( processInformation.hProcess, INFINITE ); + + // Get the exit code. + result = GetExitCodeProcess(processInformation.hProcess, &exitCode); + + // Close the handles. + CloseHandle( processInformation.hProcess ); + CloseHandle( processInformation.hThread ); + + if (!result) + return FALSE; + + // We succeeded. + return TRUE; + } +} + + +HRESULT UnzipToFolder( + MSIHANDLE hInstall, + __in LPCWSTR wzFriendlyName, + __in LPCWSTR wzTarGzFileName, + __in LPCWSTR wzDestPath + ) +{ + HRESULT hr = S_OK; + + WcaLog(LOGMSG_STANDARD, "Extract \"%S\" package initialized.", wzFriendlyName); + + wchar_t szSourceDir[BUF_LEN] = L""; DWORD nSourceDirDirLen = BUF_LEN; + wchar_t szTarGzFilePath[BUF_LEN] = L""; + wchar_t szTarFilePath[BUF_LEN] = L""; + MsiGetProperty(hInstall, L"SourceDir", szSourceDir, &nSourceDirDirLen); + StringCchPrintf(szTarGzFilePath, BUF_LEN, L"%s%s", szSourceDir, wzTarGzFileName); + StringCchPrintf(szTarFilePath, BUF_LEN, L"%s*.tar", szSourceDir); + + DWORD pdwAttr; + if (FileExistsEx(szTarGzFilePath, &pdwAttr) == TRUE) + { + //Extacting quality_cloud_production.sql to %TEMP% folder + wchar_t szTmpDir[BUF_LEN] = L""; DWORD nTmpDirLen = BUF_LEN; + wchar_t sz7Zip[BUF_LEN] = L""; + + wchar_t szCommandLine1[BUF_LEN] = L""; + wchar_t szCommandLine2[BUF_LEN] = L""; + + MsiGetProperty(hInstall, L"TempFolder", szTmpDir, &nTmpDirLen); + StringCchPrintf(sz7Zip, BUF_LEN, L"%s%s", szTmpDir, L"7za.exe"); + + DWORD pdwAttr; + if (FileExistsEx(sz7Zip, &pdwAttr) == FALSE) + { + hr = ExtractBinaryToFile(L"SevenZip", sz7Zip); + } + + StringCchPrintf(szCommandLine1, BUF_LEN, L"\"%s\" x -o\"%s\" -y \"%s\"", sz7Zip, szSourceDir, szTarGzFilePath); + StringCchPrintf(szCommandLine2, BUF_LEN, L"\"%s\" x -o\"%s\" -y \"%s\"", sz7Zip, wzDestPath, szTarFilePath); + DWORD nRes=0; + LPTSTR ErrorMessage = NULL; + + ExecuteCommandLine(szCommandLine1, nRes); + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, HRESULT_FROM_WIN32(nRes), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&ErrorMessage, 0, NULL); + if (NULL != ErrorMessage) WcaLog(LOGMSG_STANDARD, "Archive expanding completed with (%d): %S", nRes, ErrorMessage); + + ExecuteCommandLine(szCommandLine2, nRes); + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, HRESULT_FROM_WIN32(nRes), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&ErrorMessage, 0, NULL); + if (NULL != ErrorMessage) WcaLog(LOGMSG_STANDARD, "Archive deployment completed with (%d): %S", nRes, ErrorMessage); + } + else + { + hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); + WcaLog(LOGMSG_STANDARD, "Failed to extract %S files. File not found: %S", wzFriendlyName, szTarGzFilePath); + } + + WcaLog(LOGMSG_STANDARD, "Extracting \"%S\" package completed.", wzFriendlyName); + + return hr; +} + + +UINT __stdcall Extract_MeteorFiles(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + hr = WcaInitialize(hInstall, "Extract_MeteorFiles"); + ExitOnFailure(hr, "Failed to initialize Extract_MeteorFiles"); + + wchar_t szMeteorDir[BUF_LEN] = L""; DWORD nMeteorDirLen = BUF_LEN; + MsiGetProperty(hInstall, L"METEOR_DIR", szMeteorDir, &nMeteorDirLen); + + hr = UnzipToFolder(hInstall, L"Meteor", L"meteor-bootstrap-os.windows.x86_32.tar.gz", szMeteorDir); + ExitOnFailure(hr, "Failed to extract Meteor files."); + +LExit: + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + + + +HRESULT Download_Package( + MSIHANDLE hInstall, + __in LPCWSTR wzFriendlyName, + __in LPCWSTR wzProperty_DWNURL, + __in LPCWSTR wzZipFile) +{ + HRESULT hr = S_OK; + + WcaLog(LOGMSG_STANDARD, "Download package \"%S\" initialized.", wzFriendlyName); + + wchar_t szSourceDir[BUF_LEN] = L""; DWORD nSourceDirDirLen = BUF_LEN; + wchar_t szDwnUrl[BUF_LEN] = L""; DWORD nDwnUrlLen = BUF_LEN; + wchar_t szDwnUser[BUF_LEN] = L""; DWORD nDwnUserLen = BUF_LEN; + wchar_t szDwnPass[BUF_LEN] = L""; DWORD nDwnPassLen = BUF_LEN; + wchar_t szZipFile[BUF_LEN] = L""; + + MsiGetProperty(hInstall, L"SourceDir", szSourceDir, &nSourceDirDirLen); + MsiGetProperty(hInstall, wzProperty_DWNURL, szDwnUrl, &nDwnUrlLen); + MsiGetProperty(hInstall, L"HTTP_DWN_USER", szDwnUser, &nDwnUserLen); + MsiGetProperty(hInstall, L"HTTP_DWN_PASS", szDwnPass, &nDwnPassLen); + StringCchPrintf(szZipFile, BUF_LEN, L"%s%s", szSourceDir, wzZipFile); + + // Checking for Prerequisites\localFile + wchar_t szBundleSrc[BUF_LEN] = L""; DWORD nBundleSrcLen = BUF_LEN; + wchar_t szPrereqDir[BUF_LEN] = L""; DWORD nPrereqDirLen = BUF_LEN; + wchar_t szLocalFile[BUF_LEN] = L""; + wchar_t* szBundlePath; + MsiGetProperty(hInstall, L"BUNDLE_SOURCE", szBundleSrc, &nBundleSrcLen); + MsiGetProperty(hInstall, L"PREREQ_FOLDER", szPrereqDir, &nPrereqDirLen); + PathGetDirectory(szBundleSrc, &szBundlePath); + StringCchPrintf(szLocalFile, BUF_LEN, L"%s%s\\%s", szBundlePath, szPrereqDir, wzZipFile); + + // If local file exists use it instaead of download. + DWORD pdwAttr; + if (FileExistsEx(szLocalFile, &pdwAttr) == TRUE) + { + FileEnsureCopy(szLocalFile, szZipFile, TRUE); + WcaLog(LOGMSG_STANDARD, "Nginx local package found \"%S\", will use that.", szLocalFile); + } + else + { + MyCallback pCallback; + pCallback.iHInstall = hInstall; + hr = URLDownloadToFile(NULL, szDwnUrl, szZipFile, 0, &pCallback); + + if (FAILED(hr)) + WcaLog(LOGMSG_STANDARD, "Failed to download %S package from url: %S", wzFriendlyName, szDwnUrl); + else + WcaLog(LOGMSG_STANDARD, "%S package should be here: %S", wzFriendlyName, szZipFile); + } + + WcaLog(LOGMSG_STANDARD, "Download package \"%S\" completed.", wzFriendlyName); + + return hr; +} + + + +UINT __stdcall Download_MeteorPackage(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + hr = WcaInitialize(hInstall, "Download_MeteorPackage"); + ExitOnFailure(hr, "Failed to initialize Download_MeteorPackage"); + + hr = Download_Package(hInstall, L"Meteor", L"METEOR_DWN_URL", L"meteor-bootstrap-os.windows.x86_32.tar.gz"); + ExitOnFailure(hr, "Failed to download Meteor package from specified URL."); + +LExit: + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + + + + +UINT __stdcall BulkRemoveMeteorFiles(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + hr = WcaInitialize(hInstall, "BulkRemoveMeteorFiles"); + ExitOnFailure(hr, "Failed to initialize BulkRemoveMeteorFiles"); + + WcaLog(LOGMSG_STANDARD, "BulkRemoveMeteorFiles Initialized."); + + wchar_t szPathPackages[BUF_LEN] = L""; DWORD nPathPackages = BUF_LEN; + wchar_t szPathPkg_Meta[BUF_LEN] = L""; DWORD nPathPkg_Meta = BUF_LEN; + + MsiGetProperty(hInstall, L"METEORDIR_PACKAGES", szPathPackages, &nPathPackages); + MsiGetProperty(hInstall, L"METEORDIR_PKG_META", szPathPkg_Meta, &nPathPkg_Meta); + + wchar_t szSysDir[BUF_LEN] = L""; DWORD nSysDirLen = BUF_LEN; + wchar_t szCmd1[BUF_LEN] = L""; + wchar_t szCmd2[BUF_LEN] = L""; + + DWORD nRes=0; + + + MsiGetProperty(hInstall, L"SystemFolder", szSysDir, &nSysDirLen); + StringCchPrintf(szCmd1, BUF_LEN, L"%s\\cmd.exe /C \"RD /S /Q \"%s\">NUL\"", szSysDir, szPathPackages); + StringCchPrintf(szCmd2, BUF_LEN, L"%s\\cmd.exe /C \"RD /S /Q \"%s\">NUL\"", szSysDir, szPathPkg_Meta); + + ExecuteCommandLine(szCmd1, nRes); + ExecuteCommandLine(szCmd2, nRes); + + WcaLog(LOGMSG_STANDARD, "BulkRemoveMeteorFiles done."); + +LExit: + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + + + + +// DllMain - Initialize and cleanup WiX custom action utils. +extern "C" BOOL WINAPI DllMain( + __in HINSTANCE hInst, + __in ULONG ulReason, + __in LPVOID + ) +{ + switch(ulReason) + { + case DLL_PROCESS_ATTACH: + WcaGlobalInitialize(hInst); + break; + + case DLL_PROCESS_DETACH: + WcaGlobalFinalize(); + break; + } + + return TRUE; +} diff --git a/scripts/windows/wix-installer/WiXHelper/WiXHelper.vcxproj b/scripts/windows/wix-installer/WiXHelper/WiXHelper.vcxproj index 0f793bf02f..cd392d640a 100755 --- a/scripts/windows/wix-installer/WiXHelper/WiXHelper.vcxproj +++ b/scripts/windows/wix-installer/WiXHelper/WiXHelper.vcxproj @@ -1,128 +1,128 @@ - - - - - Release - Win32 - - - Release - x64 - - - - {17815519-26F7-4F37-9FAC-3FC50796C25D} - WiXHelper - Win32Proj - - - - DynamicLibrary - Unicode - true - v100 - - - DynamicLibrary - Unicode - true - v100 - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - bin\$(Configuration)\Win32\ - obj\$(Configuration)\Win32\ - false - false - AllRules.ruleset - AllRules.ruleset - - - - - - - bin\$(Configuration)\Win64\ - obj\$(Configuration)\Win64\ - - - - MaxSpeed - true - ..\WiXSDK\inc;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;CUSTOMACTIONTEST_EXPORTS;%(PreprocessorDefinitions) - MultiThreaded - true - Use - Level3 - ProgramDatabase - - - msi.lib;dutil.lib;wcautil.lib;Version.lib;Urlmon.lib;Wininet.lib;Userenv.lib;%(AdditionalDependencies) - ..\WiXSDK\VS2010\lib\x86;%(AdditionalLibraryDirectories) - CustomAction.def - true - Windows - true - true - MachineX86 - - - - - - - - - MaxSpeed - true - ..\WiXSDK\inc;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;CUSTOMACTIONTEST_EXPORTS;%(PreprocessorDefinitions) - MultiThreaded - true - Use - Level3 - ProgramDatabase - - - msi.lib;dutil.lib;wcautil.lib;Version.lib;Urlmon.lib;Wininet.lib;Userenv.lib;%(AdditionalDependencies) - ..\WiXSDK\VS2010\lib\x64;%(AdditionalLibraryDirectories) - CustomAction.def - true - Windows - true - true - - - - - - - - - - Create - Create - - - - - - - - - - - - + + + + + Release + Win32 + + + Release + x64 + + + + {17815519-26F7-4F37-9FAC-3FC50796C25D} + WiXHelper + Win32Proj + + + + DynamicLibrary + Unicode + true + v100 + + + DynamicLibrary + Unicode + true + v100 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + bin\$(Configuration)\Win32\ + obj\$(Configuration)\Win32\ + false + false + AllRules.ruleset + AllRules.ruleset + + + + + + + bin\$(Configuration)\Win64\ + obj\$(Configuration)\Win64\ + + + + MaxSpeed + true + ..\WiXSDK\inc;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;CUSTOMACTIONTEST_EXPORTS;%(PreprocessorDefinitions) + MultiThreaded + true + Use + Level3 + ProgramDatabase + + + msi.lib;dutil.lib;wcautil.lib;Version.lib;Urlmon.lib;Wininet.lib;Userenv.lib;%(AdditionalDependencies) + ..\WiXSDK\VS2010\lib\x86;%(AdditionalLibraryDirectories) + CustomAction.def + true + Windows + true + true + MachineX86 + + + + + + + + + MaxSpeed + true + ..\WiXSDK\inc;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;CUSTOMACTIONTEST_EXPORTS;%(PreprocessorDefinitions) + MultiThreaded + true + Use + Level3 + ProgramDatabase + + + msi.lib;dutil.lib;wcautil.lib;Version.lib;Urlmon.lib;Wininet.lib;Userenv.lib;%(AdditionalDependencies) + ..\WiXSDK\VS2010\lib\x64;%(AdditionalLibraryDirectories) + CustomAction.def + true + Windows + true + true + + + + + + + + + + Create + Create + + + + + + + + + + + + \ No newline at end of file diff --git a/scripts/windows/wix-installer/WiXHelper/WiXHelper.vcxproj.filters b/scripts/windows/wix-installer/WiXHelper/WiXHelper.vcxproj.filters index 3fc884f024..5837c344d6 100755 --- a/scripts/windows/wix-installer/WiXHelper/WiXHelper.vcxproj.filters +++ b/scripts/windows/wix-installer/WiXHelper/WiXHelper.vcxproj.filters @@ -1,38 +1,38 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav - - - - - Source Files - - - Source Files - - - - - Source Files - - - - - Header Files - - - Header Files - - + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + + + Source Files + + + Source Files + + + + + Source Files + + + + + Header Files + + + Header Files + + \ No newline at end of file diff --git a/scripts/windows/wix-installer/WiXInstaller/.gitignore b/scripts/windows/wix-installer/WiXInstaller/.gitignore new file mode 100644 index 0000000000..57a1574c4f --- /dev/null +++ b/scripts/windows/wix-installer/WiXInstaller/.gitignore @@ -0,0 +1,196 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Visual Studo 2015 cache/options directory +.vs/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding addin-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +*.[Cc]ache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt diff --git a/scripts/windows/wix-installer/WiXInstaller/Configuration.wxi b/scripts/windows/wix-installer/WiXInstaller/Configuration.wxi_ old mode 100755 new mode 100644 similarity index 87% rename from scripts/windows/wix-installer/WiXInstaller/Configuration.wxi rename to scripts/windows/wix-installer/WiXInstaller/Configuration.wxi_ index fb17ac943f..f4c78cb028 --- a/scripts/windows/wix-installer/WiXInstaller/Configuration.wxi +++ b/scripts/windows/wix-installer/WiXInstaller/Configuration.wxi_ @@ -5,7 +5,7 @@ - + @@ -23,6 +23,6 @@ - + - \ No newline at end of file + diff --git a/scripts/windows/wix-installer/WiXInstaller/MSIPackage.wixproj b/scripts/windows/wix-installer/WiXInstaller/MSIPackage.wixproj index f2f0377f8b..3ed8349c5b 100755 --- a/scripts/windows/wix-installer/WiXInstaller/MSIPackage.wixproj +++ b/scripts/windows/wix-installer/WiXInstaller/MSIPackage.wixproj @@ -1,65 +1,65 @@ - - - - Debug - x86 - {e053726b-937b-40c7-8f3d-25a3226979d9} - 2.0 - Package - $(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets - $(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets - MSIPackage - 6.0.2469 - - - bin\$(Configuration)\$(Platform)\ - obj\$(Platform)\$(Configuration)\ - - - x86 - ICE60;ICE80 - SetupMeteor - - - bin\$(Configuration)\$(Platform)\ - obj\$(Platform)\$(Configuration)\ - - - x64 - ICE60;ICE61;ICE69; - SetupMeteor - - - - - - $(WixExtDir)\WixNetFxExtension.dll - WixNetFxExtension - - - $(WixExtDir)\WixFirewallExtension.dll - WixFirewallExtension - - - $(WixExtDir)\WixUtilExtension.dll - WixUtilExtension - - - - - - - - Configuration.wxi - - - - - - - - - + + + + Debug + x86 + {e053726b-937b-40c7-8f3d-25a3226979d9} + 2.0 + Package + $(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets + $(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets + MSIPackage + 6.0.2469 + + + bin\$(Configuration)\$(Platform)\ + obj\$(Platform)\$(Configuration)\ + + + x86 + ICE60;ICE80 + SetupMeteor + + + bin\$(Configuration)\$(Platform)\ + obj\$(Platform)\$(Configuration)\ + + + x64 + ICE60;ICE61;ICE69; + SetupMeteor + + + + + + $(WixExtDir)\WixNetFxExtension.dll + WixNetFxExtension + + + $(WixExtDir)\WixFirewallExtension.dll + WixFirewallExtension + + + $(WixExtDir)\WixUtilExtension.dll + WixUtilExtension + + + + + + + + Configuration.wxi + + + + + + + + + +--> \ No newline at end of file diff --git a/scripts/windows/wix-installer/WiXInstaller/Meteor_Bundle.wxs b/scripts/windows/wix-installer/WiXInstaller/Meteor_Bundle.wxs index 076d14f700..a68c09ccd7 100755 --- a/scripts/windows/wix-installer/WiXInstaller/Meteor_Bundle.wxs +++ b/scripts/windows/wix-installer/WiXInstaller/Meteor_Bundle.wxs @@ -1,73 +1,73 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/windows/wix-installer/WiXInstaller/Meteor_Product.wxs b/scripts/windows/wix-installer/WiXInstaller/Meteor_Product.wxs index 32a16b6b20..b14d032d42 100755 --- a/scripts/windows/wix-installer/WiXInstaller/Meteor_Product.wxs +++ b/scripts/windows/wix-installer/WiXInstaller/Meteor_Product.wxs @@ -1,87 +1,87 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - NOT Installed - NOT Installed - REMOVE~="ALL" - REMOVE~="ALL" - REMOVE~="ALL" - - - - Installing Meteor files ... - Removing Meteor files ... - - - - - - - - NOT Installed AND PERUSER_INSTALL - - - - - NOT Installed AND PERMACHINE_INSTALL - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NOT Installed + NOT Installed + REMOVE~="ALL" + REMOVE~="ALL" + REMOVE~="ALL" + + + + Installing Meteor files ... + Removing Meteor files ... + + + + + + + + NOT Installed AND PERUSER_INSTALL + + + + + NOT Installed AND PERMACHINE_INSTALL + + + + + + + + + + + diff --git a/scripts/windows/wix-installer/WiXInstaller/Resources/Theme_Meteor.wxl b/scripts/windows/wix-installer/WiXInstaller/Resources/Theme_Meteor.wxl index bebe517119..6c6e650be5 100755 --- a/scripts/windows/wix-installer/WiXInstaller/Resources/Theme_Meteor.wxl +++ b/scripts/windows/wix-installer/WiXInstaller/Resources/Theme_Meteor.wxl @@ -1,97 +1,97 @@ - - - [WixBundleName] Setup - [WixBundleName] - Welcome to the [WixBundleName] Setup - Setup will install [WixBundleName] on your computer. During the wizard, you will be able to adjust product features and settings that fit best to your needs. - Version [WixBundleVersion] - By installing this application you have to read, understood and agree [WixBundleName]'s <a href="[TermsUrl]">Terms of Use</a> and <a href="[PrivacyUrl]">Privacy Policy</a>. - Are you sure you want to cancel? - Setup Help - - /install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or creates a complete local copy of the bundle in directory. Install is the default. - - /passive | /quiet - displays minimal UI with no prompts or displays no UI and no prompts. By default UI and all prompts are displayed. - - /norestart - suppress any attempts to restart. By default UI will prompt before restart. - - /log log.txt - logs to a specific file. By default a log file is created in %TEMP%. - - &Close - I &agree to the license terms and conditions - &Options - &Install - &Cancel - < Back - Next > - Install [WixBundleName] - - Version [WixBundleVersion] <a href="#">upgrade available</a> - Current user password: - - [WixBundleName] install directory - Please select the way you want [WixBundleName] to be installed on your computer. - Install location: - Install this application for: - For all users on this computer (recommended) - Only for me ([LogonUser]) - - [WixBundleName] registration - In order to continue it is recommended to configure your meteor developer account. - Create a new developer account - Sign In using an existing developer account - E-mail Address - User Name - Password - Skip [WixBundleName] registration and continue with setup - - - - Setup Options - Adjust setup parameters in order to your needs. - Install location: - &Browse... - Database location: - B&rowse... - &OK - &Cancel - - - - - Installing [WixBundleName] - Repairing [WixBundleName] - Uninstalling [WixBundleName] - Please wait while Setup installs [WixBundleName] on your computer. - Please wait while Setup repairs [WixBundleName] installed on your computer. - Please wait while [WixBundleName] is removed from your computer. - Processing: - Initializing... - Initializing... - Initializing... - - &Cancel - [WixBundleName] Maintenance - The setup wizard allows you to repair or remove the [WixBundleName] on your computer. If you have a previous [WixBundleName] application currently running, it is recommended to close it. Click Repair if you want to repair [WixBundleName], Uninstall to remove it or click Cancel to close this maintenance wizard. - &Repair - &Uninstall - &Close - Setup Successful - Repair Successful - Uninstall Successful - Setup has finished installing [WixBundleName] on your computer. Open a commandprompt window and type "meteor" to start. - Following non critical errors occured: - Setup has finished repairing [WixBundleName] installed on your computer. The application may be launched by selecting the installed icons. - [WixBundleName] was successfully removed from your computer. - &Launch - You must restart your computer before you can use the software. - &Restart - &Close - Setup Failed - Repair Failed - Uninstall Failed - One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the <a href="#">log file</a>. - You must restart your computer to complete the rollback of the software. - &Restart - &Close + + + [WixBundleName] Setup + [WixBundleName] + Welcome to the [WixBundleName] Setup + Setup will install [WixBundleName] on your computer. During the wizard, you will be able to adjust product features and settings that fit best to your needs. + Version [WixBundleVersion] + By installing this application you have to read, understood and agree [WixBundleName]'s <a href="[TermsUrl]">Terms of Use</a> and <a href="[PrivacyUrl]">Privacy Policy</a>. + Are you sure you want to cancel? + Setup Help + + /install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or creates a complete local copy of the bundle in directory. Install is the default. + + /passive | /quiet - displays minimal UI with no prompts or displays no UI and no prompts. By default UI and all prompts are displayed. + + /norestart - suppress any attempts to restart. By default UI will prompt before restart. + + /log log.txt - logs to a specific file. By default a log file is created in %TEMP%. + + &Close + I &agree to the license terms and conditions + &Options + &Install + &Cancel + < Back + Next > + Install [WixBundleName] + + Version [WixBundleVersion] <a href="#">upgrade available</a> + Current user password: + + [WixBundleName] install directory + Please select the way you want [WixBundleName] to be installed on your computer. + Install location: + Install this application for: + For all users on this computer (recommended) + Only for me ([LogonUser]) + + [WixBundleName] registration + In order to continue it is recommended to configure your meteor developer account. + Create a new developer account + Sign In using an existing developer account + E-mail Address + User Name + Password + Skip [WixBundleName] registration and continue with setup + + + + Setup Options + Adjust setup parameters in order to your needs. + Install location: + &Browse... + Database location: + B&rowse... + &OK + &Cancel + + + + + Installing [WixBundleName] + Repairing [WixBundleName] + Uninstalling [WixBundleName] + Please wait while Setup installs [WixBundleName] on your computer. + Please wait while Setup repairs [WixBundleName] installed on your computer. + Please wait while [WixBundleName] is removed from your computer. + Processing: + Initializing... + Initializing... + Initializing... + + &Cancel + [WixBundleName] Maintenance + The setup wizard allows you to repair or remove the [WixBundleName] on your computer. If you have a previous [WixBundleName] application currently running, it is recommended to close it. Click Repair if you want to repair [WixBundleName], Uninstall to remove it or click Cancel to close this maintenance wizard. + &Repair + &Uninstall + &Close + Setup Successful + Repair Successful + Uninstall Successful + Setup has finished installing [WixBundleName] on your computer. Open a commandprompt window and type "meteor" to start. + Following non critical errors occured: + Setup has finished repairing [WixBundleName] installed on your computer. The application may be launched by selecting the installed icons. + [WixBundleName] was successfully removed from your computer. + &Launch + You must restart your computer before you can use the software. + &Restart + &Close + Setup Failed + Repair Failed + Uninstall Failed + One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the <a href="#">log file</a>. + You must restart your computer to complete the rollback of the software. + &Restart + &Close \ No newline at end of file diff --git a/scripts/windows/wix-installer/WiXInstaller/Resources/Theme_Meteor.xml b/scripts/windows/wix-installer/WiXInstaller/Resources/Theme_Meteor.xml index c4336a8777..237f0f812e 100755 --- a/scripts/windows/wix-installer/WiXInstaller/Resources/Theme_Meteor.xml +++ b/scripts/windows/wix-installer/WiXInstaller/Resources/Theme_Meteor.xml @@ -1,124 +1,124 @@ - - - #(loc.Caption) - Segoe UI - Segoe UI - Tahoma - Segoe UI - Tahoma - Segoe UI - Segoe UI - Segoe UI - - - - - - - #(loc.HelpHeader) - #(loc.HelpText) - - - - - - - #(loc.InstallLicenseLinkText) --> - - - - - #(loc.InstallVersion) - - - - - - #(loc.InstallDirHeader) - #(loc.InstallDirMessage) - - #(loc.InstallScopeLabel) - - - - #(loc.InstallDirPathLabel) - - - - - - - - - - - - #(loc.RegistrationHeader) - - #(loc.RegistrationInfo) - - - - - #(loc.RegisterEmail): - #(loc.RegisterUser): - #(loc.RegisterPass): - - [RegisterEmail] - [RegisterUser] - [RegisterPass] - #(loc.SkipRegistration) - - - - - - - - - - - [varProgressHeader] - [varProgressInfo] - #(loc.ExecuteProgressText) - - #(loc.ExecuteProgressActionDataText) - - - - - - #(loc.ModifyHeader) - #(loc.ModifyInfo) - - - - - - - - [varSuccessHeader] - [varSuccessInfo] - [varSuccessErrorInfoText] - [varSuccessErrorMessageText] - #(loc.SuccessRestartText) - - #(loc.InstallVersion) - - - - - - - - [varFailureHeader] - #(loc.FailureHyperlinkLogText) - - - #(loc.InstallVersion) - #(loc.FailureRestartText) - - - + + + #(loc.Caption) + Segoe UI + Segoe UI + Tahoma + Segoe UI + Tahoma + Segoe UI + Segoe UI + Segoe UI + + + + + + + #(loc.HelpHeader) + #(loc.HelpText) + + + + + + + #(loc.InstallLicenseLinkText) --> + + + + + #(loc.InstallVersion) + + + + + + #(loc.InstallDirHeader) + #(loc.InstallDirMessage) + + #(loc.InstallScopeLabel) + + + + #(loc.InstallDirPathLabel) + + + + + + + + + + + + #(loc.RegistrationHeader) + + #(loc.RegistrationInfo) + + + + + #(loc.RegisterEmail): + #(loc.RegisterUser): + #(loc.RegisterPass): + + [RegisterEmail] + [RegisterUser] + [RegisterPass] + #(loc.SkipRegistration) + + + + + + + + + + + [varProgressHeader] + [varProgressInfo] + #(loc.ExecuteProgressText) + + #(loc.ExecuteProgressActionDataText) + + + + + + #(loc.ModifyHeader) + #(loc.ModifyInfo) + + + + + + + + [varSuccessHeader] + [varSuccessInfo] + [varSuccessErrorInfoText] + [varSuccessErrorMessageText] + #(loc.SuccessRestartText) + + #(loc.InstallVersion) + + + + + + + + [varFailureHeader] + #(loc.FailureHyperlinkLogText) + + + #(loc.InstallVersion) + #(loc.FailureRestartText) + + + \ No newline at end of file diff --git a/scripts/windows/wix-installer/WiXInstaller/SetupPackage.wixproj b/scripts/windows/wix-installer/WiXInstaller/SetupPackage.wixproj index 0965cfc05a..d659db1983 100755 --- a/scripts/windows/wix-installer/WiXInstaller/SetupPackage.wixproj +++ b/scripts/windows/wix-installer/WiXInstaller/SetupPackage.wixproj @@ -1,71 +1,71 @@ - - - - Debug - x86 - 3.8 - 7b569f5b-5d73-4e7b-be41-041a2f22a521 - 2.0 - Bundle - $(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets - $(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets - SetupPackage - - - bin\$(Configuration)\$(Platform)\ - obj\$(Configuration)\ - True - True - False - Setup_Meteor - - - bin\$(Configuration)\$(Platform)\ - obj\$(Configuration)\ - True - True - False - Setup_Meteor - - - - - - - $(WixExtDir)\WixNetFxExtension.dll - WixNetFxExtension - - - ..\WiXBalExtension\build\WixBalExtensionExt.dll - WixBalExtensionExt - - - $(WixExtDir)\WixUtilExtension.dll - WixUtilExtension - - - - - - - - - - - - - - - - - copy "$(ProjectDir)$(OutDir)$(TargetFileName)" "$(ProjectDir)..\Release\" /Y - - + + + + Debug + x86 + 3.8 + 7b569f5b-5d73-4e7b-be41-041a2f22a521 + 2.0 + Bundle + $(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets + $(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets + SetupPackage + + + bin\$(Configuration)\$(Platform)\ + obj\$(Configuration)\ + True + True + False + Setup_Meteor + + + bin\$(Configuration)\$(Platform)\ + obj\$(Configuration)\ + True + True + False + Setup_Meteor + + + + + + + $(WixExtDir)\WixNetFxExtension.dll + WixNetFxExtension + + + ..\WiXBalExtension\build\WixBalExtensionExt.dll + WixBalExtensionExt + + + $(WixExtDir)\WixUtilExtension.dll + WixUtilExtension + + + + + + + + + + + + + + + + + copy "$(ProjectDir)$(OutDir)$(TargetFileName)" "$(ProjectDir)..\Release\" /Y + + \ No newline at end of file diff --git a/scripts/windows/wix-installer/build.bat b/scripts/windows/wix-installer/build.bat index c0ea5e23b5..a5c4ef7963 100755 --- a/scripts/windows/wix-installer/build.bat +++ b/scripts/windows/wix-installer/build.bat @@ -10,6 +10,8 @@ IF "%1"=="clean" GOTO :CLEAN :BUILD +if not exist Release md Release + echo Building WiXBalExtension... pushd WiXBalExtension Call Build @@ -21,7 +23,7 @@ echo Building custom action collection 32-bit library (WiXHelper project) %MSBUILD% WiXHelper\WiXHelper.vcxproj /t:Rebuild /p:Configuration="Release" /p:Platform=Win32 /p:DefineConstants="TRACE"%OUTLOG% if %errorlevel% neq 0 ( echo Build failed - pause + rem pause goto :EOF ) @@ -42,7 +44,7 @@ echo Building Meteor installer package... %MSBUILD% MeteorSetup.sln /t:Rebuild /p:Configuration="Release" /p:Platform="x86" /p:DefineConstants="TRACE"%OUTLOG% if %errorlevel% neq 0 ( echo Build failed - pause + rem pause goto :EOF )