WIP windows upgrade

WIP windows upgrade

Signed-off-by: Jeffrey Morgan <ed44c26e472545c167e88c1767e26e2a8b36f912@gmail.com>

#define MyAppName "Docker Toolbox"
#define MyAppPublisher "Docker"
#define MyAppURL "https://docker.com"
#define MyAppContact "https://docs.docker.com"

#define b2dIsoPath "..\bundle\boot2docker.iso"
#define dockerCli "..\bundle\docker.exe"
#define dockerMachineCli "..\bundle\docker-machine.exe"
#define kitematic "..\bundle\kitematic"
#define git "..\bundle\Git.exe"
#define virtualBoxCommon "..\bundle\common.cab"
#define virtualBoxMsi "..\bundle\VirtualBox_amd64.msi"

[Setup]
AppCopyright={#MyAppPublisher}
AppId={{FC4417F0-D7F3-48DB-BCE1-F5ED5BAFFD91}
AppContact={#MyAppContact}
AppComments={#MyAppURL}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
ArchitecturesAllowed=x64
ArchitecturesInstallIn64BitMode=x64
DefaultDirName={pf}\{#MyAppName}
DefaultGroupName=Docker
DisableProgramGroupPage=yes
OutputBaseFilename=DockerToolbox
Compression=lzma
SolidCompression=yes
WizardImageFile=windows-installer-side.bmp
WizardSmallImageFile=windows-installer-logo.bmp
WizardImageStretch=no
WizardImageBackColor=$22EBB8
UninstallDisplayIcon={app}\unins000.exe
SetupIconFile=toolbox.ico
ChangesEnvironment=true

[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"

[Types]
Name: "full"; Description: "Full installation"
Name: "custom"; Description: "Custom installation"; Flags: iscustom

[Run]
Filename: "{win}\explorer.exe"; Parameters: "{userprograms}\Docker\"; Flags: postinstall skipifsilent; Description: "View Shortcuts in File Explorer"

[Tasks]
Name: desktopicon; Description: "{cm:CreateDesktopIcon}"
Name: modifypath; Description: "Add docker.exe & docker-machine.exe to &PATH"

[Components]
Name: "Docker"; Description: "Docker Client for Windows" ; Types: full custom; Flags: fixed
Name: "DockerMachine"; Description: "Docker Machine for Windows" ; Types: full custom; Flags: fixed
Name: "VirtualBox"; Description: "VirtualBox"; Types: full custom; Flags: disablenouninstallwarning
Name: "Kitematic"; Description: "Kitematic for Windows (Alpha)" ; Types: full custom
Name: "Git"; Description: "Git for Windows"; Types: full custom; Flags: disablenouninstallwarning

[Files]
Source: ".\docker-quickstart-terminal.ico"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#dockerCli}"; DestDir: "{app}"; Flags: ignoreversion; Components: "Docker"
Source: ".\start.sh"; DestDir: "{app}"; Flags: ignoreversion; Components: "Docker"
Source: ".\delete.sh"; DestDir: "{app}"; Flags: ignoreversion; Components: "Docker"
Source: "{#dockerMachineCli}"; DestDir: "{app}"; Flags: ignoreversion; Components: "DockerMachine"
Source: ".\migrate.sh"; DestDir: "{app}"; Flags: ignoreversion; Components: "DockerMachine"
Source: ".\migrate.bat"; DestDir: "{app}"; Flags: ignoreversion; Components: "DockerMachine"
Source: "{#kitematic}\*"; DestDir: "{app}\kitematic"; Flags: ignoreversion recursesubdirs; Components: "Kitematic"
Source: "{#b2dIsoPath}"; DestDir: "{app}"; Flags: ignoreversion; Components: "DockerMachine"; AfterInstall: CopyBoot2DockerISO()
Source: "{#git}"; DestDir: "{app}\installers\git"; DestName: "git.exe"; AfterInstall: RunInstallGit();  Components: "Git"
Source: "{#virtualBoxCommon}"; DestDir: "{app}\installers\virtualbox"; Components: "VirtualBox"
Source: "{#virtualBoxMsi}"; DestDir: "{app}\installers\virtualbox"; DestName: "virtualbox.msi"; AfterInstall: RunInstallVirtualBox(); Components: "VirtualBox"

[Icons]
Name: "{userprograms}\Docker\Kitematic (Alpha)"; WorkingDir: "{app}"; Filename: "{app}\kitematic\Kitematic.exe"; Components: "Kitematic"
Name: "{commondesktop}\Kitematic (Alpha)"; WorkingDir: "{app}"; Filename: "{app}\kitematic\Kitematic.exe"; Tasks: desktopicon; Components: "Kitematic"
Name: "{userprograms}\Docker\Docker Quickstart Terminal"; WorkingDir: "{app}"; Filename: "{pf64}\Git\git-bash.exe"; Parameters: """{app}\start.sh"""; IconFilename: "{app}/docker-quickstart-terminal.ico"; Components: "Docker"
Name: "{commondesktop}\Docker Quickstart Terminal"; WorkingDir: "{app}"; Filename: "{pf64}\Git\git-bash.exe"; Parameters: """{app}\start.sh"""; IconFilename: "{app}/docker-quickstart-terminal.ico"; Tasks: desktopicon; Components: "Docker"

[UninstallRun]
Filename: "{app}\delete.sh"

[UninstallDelete]
Type: filesandordirs; Name: "{localappdata}\..\Roaming\Kitematic"

[Code]
#include "base64.iss"
#include "guid.iss"

var
	restart: boolean;
  TrackingDisabled: Boolean;
	DockerInstallDocs: TLabel;
  TrackingCheckBox: TNewCheckBox;

function uuid(): String;
var
  dirpath: String;
  filepath: String;
  ansiresult: AnsiString;
begin
  dirpath := ExpandConstant('{userappdata}\DockerToolbox');
  filepath := dirpath + '\id.txt';
  ForceDirectories(dirpath);

  Result := '';
  if FileExists(filepath) then
    LoadStringFromFile(filepath, ansiresult);
    Result := String(ansiresult)

  if Length(Result) = 0 then
    Result := GetGuid('');
    StringChangeEx(Result, '{', '', True);
    StringChangeEx(Result, '}', '', True);
    SaveStringToFile(filepath, AnsiString(Result), False);
end;

function WindowsVersionString(): String;
var
	ResultCode: Integer;
	lines : TArrayOfString;
begin
	if not Exec(ExpandConstant('{cmd}'), ExpandConstant('/c wmic os get caption | more +1 > C:\windows-version.txt'), '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then begin
		Result := 'N/A';
		exit;
	end;

	if LoadStringsFromFile(ExpandConstant('C:\windows-version.txt'), lines) then begin
		Result := lines[0];
	end else begin
		Result := 'N/A'
	end;
end;

procedure TrackEvent(name: String);
var
  payload: String;
  WinHttpReq: Variant;
begin
  if TrackingDisabled or WizardSilent() then
    exit;
  try
    payload := Encode64(Format(ExpandConstant('{{"event": "%s", "properties": {{"token": "{#MixpanelToken}", "distinct_id": "%s", "os": "win32", "os version": "%s", "version": "{#MyAppVersion}"}}'), [name, uuid(), WindowsVersionString()]));
    WinHttpReq := CreateOleObject('WinHttp.WinHttpRequest.5.1');
    WinHttpReq.Open('POST', 'https://api.mixpanel.com/track/?data=' + payload, false);
    WinHttpReq.SetRequestHeader('Content-Type', 'application/json');
    WinHttpReq.Send('');
  except
  end;
end;

function NeedRestart(): Boolean;
begin
	Result := restart;
end;

function NeedToInstallVirtualBox(): Boolean;
begin
	// TODO: Also compare versions
	Result := (
		(GetEnv('VBOX_INSTALL_PATH') = '')
		and
		(GetEnv('VBOX_MSI_INSTALL_PATH') = '')
	);
end;

function NeedToInstallGit(): Boolean;
begin
	// TODO: Find a better way to see if Git is installed
	Result := not DirExists('C:\Program Files\Git') or not FileExists('C:\Program Files\Git\git-bash.exe')
end;

procedure DocLinkClick(Sender: TObject);
var
	ErrorCode: Integer;
begin
	ShellExec('', 'https://docs.docker.com/installation/windows/', '', '', SW_SHOW, ewNoWait, ErrorCode);
end;

procedure TrackingCheckBoxClicked(Sender: TObject);
begin
  if TrackingCheckBox.Checked then begin
		TrackingDisabled := False;
    TrackEvent('Enabled Tracking');
  end else begin
    TrackEvent('Disabled Tracking');
    TrackingDisabled := True;
  end;
end;

procedure InitializeWizard;
var
  WelcomePage: TWizardPage;
	TrackingLabel: TLabel;
begin
	DockerInstallDocs := TLabel.Create(WizardForm);
	DockerInstallDocs.Parent := WizardForm;
	DockerInstallDocs.Left := 8;
	DockerInstallDocs.Top := WizardForm.ClientHeight - DockerInstallDocs.ClientHeight - 8;
	DockerInstallDocs.Cursor := crHand;
	DockerInstallDocs.Font.Color := clBlue;
	DockerInstallDocs.Font.Style := [fsUnderline];
	DockerInstallDocs.Caption := '{#MyAppName} installation documentation';
	DockerInstallDocs.OnClick := @DocLinkClick;
	DockerInstallDocs.Visible := True;

  WelcomePage := PageFromID(wpWelcome)

	WizardForm.WelcomeLabel2.AutoSize := True;

  TrackingCheckBox := TNewCheckBox.Create(WizardForm);
  TrackingCheckBox.Top := 168;
  TrackingCheckBox.Left := WizardForm.WelcomeLabel2.Left;
  TrackingCheckBox.Width := WizardForm.WelcomeLabel2.Width;
  TrackingCheckBox.Height := 40;
  TrackingCheckBox.Caption := 'Send one-time, anonymous diagnostics during install.';
  TrackingCheckBox.Checked := True;
  TrackingCheckBox.Parent := WelcomePage.Surface;
  TrackingCheckBox.OnClick := @TrackingCheckboxClicked;

	TrackingLabel := TLabel.Create(WizardForm);
	TrackingLabel.Parent := WelcomePage.Surface;
	TrackingLabel.Font := WizardForm.WelcomeLabel2.Font;
	TrackingLabel.Font.Color := clGray;
  TrackingLabel.Caption := 'This data helps us detect problems and improve the installation experience. We only use it for aggregate statistics and will never share it with third parties.';
	TrackingLabel.WordWrap := True;
	TrackingLabel.Visible := True;
	TrackingLabel.Left := WizardForm.WelcomeLabel2.Left;
	TrackingLabel.Width := WizardForm.WelcomeLabel2.Width;
	TrackingLabel.Top := 200;
	TrackingLabel.Height := 100;

	WizardForm.FinishedLabel.AutoSize := True;
	WizardForm.FinishedLabel.Caption :=
		'{#MyAppName} installation completed.' + \
		#13#10 + \
		#13#10 + \
		'Run using the `Docker Quickstart Terminal` icon on your desktop or in [Program Files] - then start a test container with:' + \
		#13#10 + \
		'         `docker run hello-world`' + \
		#13#10 + \
		#13#10 + \
		// TODO: it seems making hyperlinks is hard :/
		//'To save and share container images, automate workflows, and more sign-up for a free Docker Hub account.' + \
		#13#10 + \
		#13#10 +
		'You can upgrade your existing Docker Machine dev VM without data loss by running:' + \
		#13#10 + \
		'         `docker-machine upgrade dev`' + \
		#13#10 + \
		#13#10 + \
		'For further information, please see the {#MyAppName} installation documentation link.'

		// Don't do this until we can compare versions
		// Wizardform.ComponentsList.Checked[2] := NeedToInstallVirtualBox();
		Wizardform.ComponentsList.ItemEnabled[2] := not NeedToInstallVirtualBox();
		Wizardform.ComponentsList.Checked[4] := NeedToInstallGit();
		Wizardform.ComponentsList.ItemEnabled[4] := not NeedToInstallGit();
end;

function InitializeSetup(): boolean;
begin
  TrackEvent('Installer Started');
  Result := True;
end;

function NextButtonClick(CurPageID: Integer): Boolean;
begin
  if CurPageID = wpWelcome then begin
      TrackEvent('Continued from Overview');
  end;
  Result := True
end;

procedure RunInstallVirtualBox();
var
	ResultCode: Integer;
begin
	WizardForm.FilenameLabel.Caption := 'installing VirtualBox'
	if not Exec(ExpandConstant('msiexec'), ExpandConstant('/qn /i "{app}\installers\virtualbox\virtualbox.msi" /norestart'), '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then
		MsgBox('virtualbox install failure', mbInformation, MB_OK);
end;

procedure RunInstallGit();
var
	ResultCode: Integer;
begin
	WizardForm.FilenameLabel.Caption := 'installing Git for Windows'
	if Exec(ExpandConstant('{app}\installers\git\git.exe'), '/sp- /verysilent /norestart', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then
	begin
		// handle success if necessary; ResultCode contains the exit code
		//MsgBox('git installed OK', mbInformation, MB_OK);
	end
	else begin
		// handle failure if necessary; ResultCode contains the error code
		MsgBox('git install failure', mbInformation, MB_OK);
	end;
end;

procedure CopyBoot2DockerISO();
begin
  WizardForm.FilenameLabel.Caption := 'copying boot2docker iso'
  if not ForceDirectories(ExpandConstant('{userdocs}\..\.docker\machine\cache')) then
      MsgBox('Failed to create docker machine cache dir', mbError, MB_OK);
  if not FileCopy(ExpandConstant('{app}\boot2docker.iso'), ExpandConstant('{userdocs}\..\.docker\machine\cache\boot2docker.iso'), false) then
      MsgBox('File moving failed!', mbError, MB_OK);
end;

function CanMigrateVM(): Boolean;
var
	ResultCode: Integer;
begin
	if NeedToInstallGit() or NeedToInstallVirtualBox() or not FileExists(ExpandConstant('{app}\docker-machine.exe')) then begin
		Result := false
		exit
	end;

	ExecAsOriginalUser('C:\Program Files\Oracle\VirtualBox\VBoxManage.exe', 'showvminfo default', '', SW_HIDE, ewWaitUntilTerminated, ResultCode)
	if ResultCode <> 1 then begin
		Result := false
		exit
	end;

	ExecAsOriginalUser('C:\Program Files\Oracle\VirtualBox\VBoxManage.exe', 'showvminfo boot2docker-vm', '', SW_HIDE, ewWaitUntilTerminated, ResultCode)
	if ResultCode <> 0 then begin
		Result := false
		exit
	end;
	Result := true
end;

function CanUpgradeVM(): Boolean;
var
	ResultCode: Integer;
begin
	if NeedToInstallGit() or NeedToInstallVirtualBox() or not FileExists(ExpandConstant('{app}\docker-machine.exe')) then begin
		Result := false
		exit
	end;

	ExecAsOriginalUser('C:\Program Files\Oracle\VirtualBox\VBoxManage.exe', 'showvminfo default', '', SW_HIDE, ewWaitUntilTerminated, ResultCode)
	if ResultCode <> 0 then begin
		Result := false
		exit
	end;

	if not DirExists(ExpandConstant('{userdocs}\..\.docker\machine\default')) then begin
		Result := false
		exit
	end;

	// TODO: Check versions in machine
	Result := true
end;

function UpgradeVM() : Boolean;
var
	ResultCode: Integer;
begin
	TrackEvent('VM Upgrade Started');
	ExecAsOriginalUser(ExpandConstant('{app}\docker-machine.exe'), ExpandConstant('upgrade default > {localappdata}\Temp\toolbox-upgrade-logs.txt 2>&1'), '', SW_HIDE, ewWaitUntilTerminated, ResultCode)
	if ResultCode = 0 then
	begin
		TrackEvent('VM Upgrade Succeeded');
		MsgBox('Succcessfully migrated Boot2Docker VM to a Docker Machine VM named "default"', mbInformation, MB_OK);
	end
	else begin
		TrackEvent('VM Upgrade Failed');
		MsgBox('VM Upgrade VM failed. Please file an issue with the migration logs at https://github.com/docker/toolbox/issues/new.', mbCriticalError, MB_OK);
		Exec(ExpandConstant('{win}\notepad.exe'), ExpandConstant('{localappdata}\Temp\toolbox-upgrade-logs.txt'), '', SW_SHOW, ewNoWait, ResultCode)
		Result := false
		WizardForm.Close;
		exit;
	end;
	Result := true
end;

function MigrateVM() : Boolean;
var
  ResultCode: Integer;
begin
  if MsgBox('Migrate your existing Boot2Docker VM to work with the Docker Toolbox? Your existing Boot2Docker VM will not be affected. This should take about a minute.', mbConfirmation, MB_YESNO) = IDYES then
  begin
		TrackEvent('Boot2Docker Migration Started');
    WizardForm.StatusLabel.Caption := 'Migrating Boot2Docker VM...'
    WizardForm.FilenameLabel.Caption := 'This will take a minute...'
    ExecAsOriginalUser(ExpandConstant('{app}\docker-machine.exe'), ExpandConstant('rm -f default > nul 2>&1'), '', SW_HIDE, ewWaitUntilTerminated, ResultCode)
    DelTree(ExpandConstant('{userdocs}\..\.docker\machine\machines\default'), True, True, True);
    ExecAsOriginalUser(ExpandConstant('{app}\migrate.bat'), ExpandConstant('> {localappdata}\Temp\toolbox-migration-logs.txt 2>&1'), '', SW_HIDE, ewWaitUntilTerminated, ResultCode)
    if ResultCode = 0 then
    begin
      TrackEvent('Boot2Docker Migration Succeeded');
      MsgBox('Succcessfully migrated Boot2Docker VM to a Docker Machine VM named "default"', mbInformation, MB_OK);
    end
    else begin
      TrackEvent('Boot2Docker Migration Failed');
      MsgBox('Migration of Boot2Docker VM failed. Please file an issue with the migration logs at https://github.com/docker/toolbox/issues/new.', mbCriticalError, MB_OK);
      Exec(ExpandConstant('{win}\notepad.exe'), ExpandConstant('{localappdata}\Temp\toolbox-migration-logs.txt'), '', SW_SHOW, ewNoWait, ResultCode)
      Result := false
			WizardForm.Close;
      exit;
    end;
  end
  else
  begin
    TrackEvent('Boot2Docker Migration Skipped');
  end;
  Result := true
end;

const
	ModPathName = 'modifypath';
	ModPathType = 'user';

function ModPathDir(): TArrayOfString;
begin
	setArrayLength(Result, 1);
	Result[0] := ExpandConstant('{app}');
end;
#include "modpath.iss"

procedure CurStepChanged(CurStep: TSetupStep);
var
	Success: Boolean;
begin
	Success := True;
	if CurStep = ssPostInstall then
  begin
    if IsTaskSelected(ModPathName) then
			ModPath();
    if not WizardSilent() then
		begin
		if CanUpgradeVM() then
			Success := UpgradeVM();
		else if CanMigrateVM() then
			Success := MigrateVM();
		end;
		if Success then
			trackEvent('Installer Finished');
  end;
end;

#define MyAppName "Docker Toolbox"
#define MyAppPublisher "Docker"
#define MyAppURL "https://docker.com"
#define MyAppContact "https://docs.docker.com"

#define b2dIsoPath "..\bundle\boot2docker.iso"
#define dockerCli "..\bundle\docker.exe"
#define dockerMachineCli "..\bundle\docker-machine.exe"
#define kitematic "..\bundle\kitematic"
#define git "..\bundle\Git.exe"
#define virtualBoxCommon "..\bundle\common.cab"
#define virtualBoxMsi "..\bundle\VirtualBox_amd64.msi"

[Setup]
AppCopyright={#MyAppPublisher}
AppId={{FC4417F0-D7F3-48DB-BCE1-F5ED5BAFFD91}
AppContact={#MyAppContact}
AppComments={#MyAppURL}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
ArchitecturesAllowed=x64
ArchitecturesInstallIn64BitMode=x64
DefaultDirName={pf}\{#MyAppName}
DefaultGroupName=Docker
DisableProgramGroupPage=yes
OutputBaseFilename=DockerToolbox
Compression=lzma
SolidCompression=yes
WizardImageFile=windows-installer-side.bmp
WizardSmallImageFile=windows-installer-logo.bmp
WizardImageStretch=no
WizardImageBackColor=$22EBB8
UninstallDisplayIcon={app}\unins000.exe
SetupIconFile=toolbox.ico
ChangesEnvironment=true

[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"

[Types]
Name: "full"; Description: "Full installation"
Name: "custom"; Description: "Custom installation"; Flags: iscustom

[Run]
Filename: "{win}\explorer.exe"; Parameters: "{userprograms}\Docker\"; Flags: postinstall skipifsilent; Description: "View Shortcuts in File Explorer"

[Tasks]
Name: desktopicon; Description: "{cm:CreateDesktopIcon}"
Name: modifypath; Description: "Add docker.exe & docker-machine.exe to &PATH"

[Components]
Name: "Docker"; Description: "Docker Client for Windows" ; Types: full custom; Flags: fixed
Name: "DockerMachine"; Description: "Docker Machine for Windows" ; Types: full custom; Flags: fixed
Name: "VirtualBox"; Description: "VirtualBox"; Types: full custom; Flags: disablenouninstallwarning
Name: "Kitematic"; Description: "Kitematic for Windows (Alpha)" ; Types: full custom
Name: "Git"; Description: "Git for Windows"; Types: full custom; Flags: disablenouninstallwarning

[Files]
Source: ".\docker-quickstart-terminal.ico"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#dockerCli}"; DestDir: "{app}"; Flags: ignoreversion; Components: "Docker"
Source: ".\start.sh"; DestDir: "{app}"; Flags: ignoreversion; Components: "Docker"
Source: ".\delete.sh"; DestDir: "{app}"; Flags: ignoreversion; Components: "Docker"
Source: "{#dockerMachineCli}"; DestDir: "{app}"; Flags: ignoreversion; Components: "DockerMachine"
Source: ".\migrate.sh"; DestDir: "{app}"; Flags: ignoreversion; Components: "DockerMachine"
Source: ".\migrate.bat"; DestDir: "{app}"; Flags: ignoreversion; Components: "DockerMachine"
Source: "{#kitematic}\*"; DestDir: "{app}\kitematic"; Flags: ignoreversion recursesubdirs; Components: "Kitematic"
Source: "{#b2dIsoPath}"; DestDir: "{app}"; Flags: ignoreversion; Components: "DockerMachine"; AfterInstall: CopyBoot2DockerISO()
Source: "{#git}"; DestDir: "{app}\installers\git"; DestName: "git.exe"; AfterInstall: RunInstallGit();  Components: "Git"
Source: "{#virtualBoxCommon}"; DestDir: "{app}\installers\virtualbox"; Components: "VirtualBox"
Source: "{#virtualBoxMsi}"; DestDir: "{app}\installers\virtualbox"; DestName: "virtualbox.msi"; AfterInstall: RunInstallVirtualBox(); Components: "VirtualBox"

[Icons]
Name: "{userprograms}\Docker\Kitematic (Alpha)"; WorkingDir: "{app}"; Filename: "{app}\kitematic\Kitematic.exe"; Components: "Kitematic"
Name: "{commondesktop}\Kitematic (Alpha)"; WorkingDir: "{app}"; Filename: "{app}\kitematic\Kitematic.exe"; Tasks: desktopicon; Components: "Kitematic"
Name: "{userprograms}\Docker\Docker Quickstart Terminal"; WorkingDir: "{app}"; Filename: "{pf64}\Git\git-bash.exe"; Parameters: """{app}\start.sh"""; IconFilename: "{app}/docker-quickstart-terminal.ico"; Components: "Docker"
Name: "{commondesktop}\Docker Quickstart Terminal"; WorkingDir: "{app}"; Filename: "{pf64}\Git\git-bash.exe"; Parameters: """{app}\start.sh"""; IconFilename: "{app}/docker-quickstart-terminal.ico"; Tasks: desktopicon; Components: "Docker"

[UninstallRun]
Filename: "{app}\delete.sh"

[UninstallDelete]
Type: filesandordirs; Name: "{localappdata}\..\Roaming\Kitematic"

[Code]
#include "base64.iss"
#include "guid.iss"

var
	restart: boolean;
  TrackingDisabled: Boolean;
	DockerInstallDocs: TLabel;
  TrackingCheckBox: TNewCheckBox;

function uuid(): String;
var
  dirpath: String;
  filepath: String;
  ansiresult: AnsiString;
begin
  dirpath := ExpandConstant('{userappdata}\DockerToolbox');
  filepath := dirpath + '\id.txt';
  ForceDirectories(dirpath);

  Result := '';
  if FileExists(filepath) then
    LoadStringFromFile(filepath, ansiresult);
    Result := String(ansiresult)

  if Length(Result) = 0 then
    Result := GetGuid('');
    StringChangeEx(Result, '{', '', True);
    StringChangeEx(Result, '}', '', True);
    SaveStringToFile(filepath, AnsiString(Result), False);
end;

function WindowsVersionString(): String;
var
	ResultCode: Integer;
	lines : TArrayOfString;
begin
	if not Exec(ExpandConstant('{cmd}'), ExpandConstant('/c wmic os get caption | more +1 > C:\windows-version.txt'), '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then begin
		Result := 'N/A';
		exit;
	end;

	if LoadStringsFromFile(ExpandConstant('C:\windows-version.txt'), lines) then begin
		Result := lines[0];
	end else begin
		Result := 'N/A'
	end;
end;

procedure TrackEvent(name: String);
var
  payload: String;
  WinHttpReq: Variant;
begin
  if TrackingDisabled or WizardSilent() then
    exit;
  try
    payload := Encode64(Format(ExpandConstant('{{"event": "%s", "properties": {{"token": "{#MixpanelToken}", "distinct_id": "%s", "os": "win32", "os version": "%s", "version": "{#MyAppVersion}"}}'), [name, uuid(), WindowsVersionString()]));
    WinHttpReq := CreateOleObject('WinHttp.WinHttpRequest.5.1');
    WinHttpReq.Open('POST', 'https://api.mixpanel.com/track/?data=' + payload, false);
    WinHttpReq.SetRequestHeader('Content-Type', 'application/json');
    WinHttpReq.Send('');
  except
  end;
end;

function NeedRestart(): Boolean;
begin
	Result := restart;
end;

function NeedToInstallVirtualBox(): Boolean;
begin
	// TODO: Also compare versions
	Result := (
		(GetEnv('VBOX_INSTALL_PATH') = '')
		and
		(GetEnv('VBOX_MSI_INSTALL_PATH') = '')
	);
end;

function NeedToInstallGit(): Boolean;
begin
	// TODO: Find a better way to see if Git is installed
	Result := not DirExists('C:\Program Files\Git') or not FileExists('C:\Program Files\Git\git-bash.exe')
end;

procedure DocLinkClick(Sender: TObject);
var
	ErrorCode: Integer;
begin
	ShellExec('', 'https://docs.docker.com/installation/windows/', '', '', SW_SHOW, ewNoWait, ErrorCode);
end;

procedure TrackingCheckBoxClicked(Sender: TObject);
begin
  if TrackingCheckBox.Checked then begin
		TrackingDisabled := False;
    TrackEvent('Enabled Tracking');
  end else begin
    TrackEvent('Disabled Tracking');
    TrackingDisabled := True;
  end;
end;

procedure InitializeWizard;
var
  WelcomePage: TWizardPage;
	TrackingLabel: TLabel;
begin
	DockerInstallDocs := TLabel.Create(WizardForm);
	DockerInstallDocs.Parent := WizardForm;
	DockerInstallDocs.Left := 8;
	DockerInstallDocs.Top := WizardForm.ClientHeight - DockerInstallDocs.ClientHeight - 8;
	DockerInstallDocs.Cursor := crHand;
	DockerInstallDocs.Font.Color := clBlue;
	DockerInstallDocs.Font.Style := [fsUnderline];
	DockerInstallDocs.Caption := '{#MyAppName} installation documentation';
	DockerInstallDocs.OnClick := @DocLinkClick;
	DockerInstallDocs.Visible := True;

  WelcomePage := PageFromID(wpWelcome)

	WizardForm.WelcomeLabel2.AutoSize := True;

  TrackingCheckBox := TNewCheckBox.Create(WizardForm);
  TrackingCheckBox.Top := 168;
  TrackingCheckBox.Left := WizardForm.WelcomeLabel2.Left;
  TrackingCheckBox.Width := WizardForm.WelcomeLabel2.Width;
  TrackingCheckBox.Height := 40;
  TrackingCheckBox.Caption := 'Send one-time, anonymous diagnostics during install.';
  TrackingCheckBox.Checked := True;
  TrackingCheckBox.Parent := WelcomePage.Surface;
  TrackingCheckBox.OnClick := @TrackingCheckboxClicked;

	TrackingLabel := TLabel.Create(WizardForm);
	TrackingLabel.Parent := WelcomePage.Surface;
	TrackingLabel.Font := WizardForm.WelcomeLabel2.Font;
	TrackingLabel.Font.Color := clGray;
  TrackingLabel.Caption := 'This data helps us detect problems and improve the installation experience. We only use it for aggregate statistics and will never share it with third parties.';
	TrackingLabel.WordWrap := True;
	TrackingLabel.Visible := True;
	TrackingLabel.Left := WizardForm.WelcomeLabel2.Left;
	TrackingLabel.Width := WizardForm.WelcomeLabel2.Width;
	TrackingLabel.Top := 200;
	TrackingLabel.Height := 100;

	WizardForm.FinishedLabel.AutoSize := True;
	WizardForm.FinishedLabel.Caption :=
		'{#MyAppName} installation completed.' + \
		#13#10 + \
		#13#10 + \
		'Run using the `Docker Quickstart Terminal` icon on your desktop or in [Program Files] - then start a test container with:' + \
		#13#10 + \
		'         `docker run hello-world`' + \
		#13#10 + \
		#13#10 + \
		// TODO: it seems making hyperlinks is hard :/
		//'To save and share container images, automate workflows, and more sign-up for a free Docker Hub account.' + \
		#13#10 + \
		#13#10 +
		'You can upgrade your existing Docker Machine dev VM without data loss by running:' + \
		#13#10 + \
		'         `docker-machine upgrade dev`' + \
		#13#10 + \
		#13#10 + \
		'For further information, please see the {#MyAppName} installation documentation link.'

		// Don't do this until we can compare versions
		// Wizardform.ComponentsList.Checked[2] := NeedToInstallVirtualBox();
		Wizardform.ComponentsList.ItemEnabled[2] := not NeedToInstallVirtualBox();
		Wizardform.ComponentsList.Checked[4] := NeedToInstallGit();
		Wizardform.ComponentsList.ItemEnabled[4] := not NeedToInstallGit();
end;

function InitializeSetup(): boolean;
begin
  TrackEvent('Installer Started');
  Result := True;
end;

function NextButtonClick(CurPageID: Integer): Boolean;
begin
  if CurPageID = wpWelcome then begin
      TrackEvent('Continued from Overview');
  end;
  Result := True
end;

procedure RunInstallVirtualBox();
var
	ResultCode: Integer;
begin
	WizardForm.FilenameLabel.Caption := 'installing VirtualBox'
	if not Exec(ExpandConstant('msiexec'), ExpandConstant('/qn /i "{app}\installers\virtualbox\virtualbox.msi" /norestart'), '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then
		MsgBox('virtualbox install failure', mbInformation, MB_OK);
end;

procedure RunInstallGit();
var
	ResultCode: Integer;
begin
	WizardForm.FilenameLabel.Caption := 'installing Git for Windows'
	if Exec(ExpandConstant('{app}\installers\git\git.exe'), '/sp- /verysilent /norestart', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then
	begin
		// handle success if necessary; ResultCode contains the exit code
		//MsgBox('git installed OK', mbInformation, MB_OK);
	end
	else begin
		// handle failure if necessary; ResultCode contains the error code
		MsgBox('git install failure', mbInformation, MB_OK);
	end;
end;

procedure CopyBoot2DockerISO();
begin
  WizardForm.FilenameLabel.Caption := 'copying boot2docker iso'
  if not ForceDirectories(ExpandConstant('{userdocs}\..\.docker\machine\cache')) then
      MsgBox('Failed to create docker machine cache dir', mbError, MB_OK);
  if not FileCopy(ExpandConstant('{app}\boot2docker.iso'), ExpandConstant('{userdocs}\..\.docker\machine\cache\boot2docker.iso'), false) then
      MsgBox('File moving failed!', mbError, MB_OK);
end;

function MigrateVM() : Boolean;
var
  ResultCode: Integer;
begin
  if NeedToInstallGit() or NeedToInstallVirtualBox() or not FileExists(ExpandConstant('{app}\docker-machine.exe')) then begin
    Result := true
    exit
  end;

  ExecAsOriginalUser('C:\Program Files\Oracle\VirtualBox\VBoxManage.exe', 'showvminfo default', '', SW_HIDE, ewWaitUntilTerminated, ResultCode)
  if ResultCode <> 1 then begin
    Result := true
    exit
  end;

  ExecAsOriginalUser('C:\Program Files\Oracle\VirtualBox\VBoxManage.exe', 'showvminfo boot2docker-vm', '', SW_HIDE, ewWaitUntilTerminated, ResultCode)
  if ResultCode <> 0 then begin
    Result := true
    exit
  end;

  if MsgBox('Migrate your existing Boot2Docker VM to work with the Docker Toolbox? Your existing Boot2Docker VM will not be affected. This should take about a minute.', mbConfirmation, MB_YESNO) = IDYES then
  begin
		TrackEvent('Boot2Docker Migration Started');
    WizardForm.StatusLabel.Caption := 'Migrating Boot2Docker VM...'
    WizardForm.FilenameLabel.Caption := 'This will take a minute...'
    ExecAsOriginalUser(ExpandConstant('{app}\docker-machine.exe'), ExpandConstant('rm -f default > nul 2>&1'), '', SW_HIDE, ewWaitUntilTerminated, ResultCode)
    DelTree(ExpandConstant('{userdocs}\..\.docker\machine\machines\default'), True, True, True);
    ExecAsOriginalUser(ExpandConstant('{app}\migrate.bat'), ExpandConstant('> {localappdata}\Temp\toolbox-migration-logs.txt 2>&1'), '', SW_HIDE, ewWaitUntilTerminated, ResultCode)
    if ResultCode = 0 then
    begin
      TrackEvent('Boot2Docker Migration Succeeded');
      MsgBox('Succcessfully migrated Boot2Docker VM to a Docker Machine VM named "default"', mbInformation, MB_OK);
    end
    else begin
      TrackEvent('Boot2Docker Migration Failed');
      MsgBox('Migration of Boot2Docker VM failed. Please file an issue with the migration logs at https://github.com/docker/toolbox/issues/new.', mbCriticalError, MB_OK);
      Exec(ExpandConstant('{win}\notepad.exe'), ExpandConstant('{localappdata}\Temp\toolbox-migration-logs.txt'), '', SW_SHOW, ewNoWait, ResultCode)
      Result := false
			WizardForm.Close;
      exit;
    end;
  end
  else
  begin
    TrackEvent('Boot2Docker Migration Skipped');
  end;
  Result := true
end;

const
	ModPathName = 'modifypath';
	ModPathType = 'user';

function ModPathDir(): TArrayOfString;
begin
	setArrayLength(Result, 1);
	Result[0] := ExpandConstant('{app}');
end;
#include "modpath.iss"

procedure CurStepChanged(CurStep: TSetupStep);
var
	Success: Boolean;
begin
	Success := True;
	if CurStep = ssPostInstall then
  begin
    if IsTaskSelected(ModPathName) then
			ModPath();
    if not WizardSilent() then
      Success := MigrateVM();
		if Success then
			trackEvent('Installer Finished');
  end;
end;


Setup: More complete version string

Setup: More complete version string

; Script generated by the Inno Script Studio Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

#define MyAppName "Mesa3D software rendering drivers for Windows"
#define MyAppVersion "17.0.1.391-3"
#define MyAppPublisher "Pal100x"
#define MyAppURL "https://github.com/pal1000/mesa-dist-win"
#define MyAppExeName "mesa-{#MyAppVersion}-setup.exe"

[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{8EFCCC7F-5BAF-4651-A040-EFB13C59EF60}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={pf64}\{#MyAppName}
LicenseFile=..\LICENSE
OutputDir=..\bin\
OutputBaseFilename=mesa-{#MyAppVersion}-setup
Compression=lzma
SolidCompression=yes

[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"

[Files]
Source: "..\bin\x86\opengl32sw.dll"; DestDir: "{win}\system32"; Flags: ignoreversion
Source: "..\bin\x86\swrAVX.dll"; DestDir: "{win}\system32"; Flags: ignoreversion
Source: "..\bin\x86\swrAVX2.dll"; DestDir: "{win}\system32"; Flags: ignoreversion
Source: "..\bin\x86\cygwin1.dll"; DestDir: "{win}\system32"; Flags: ignoreversion
Source: "..\bin\x86\dxtn.dll"; DestDir: "{win}\system32"; Flags: ignoreversion
Source: "..\bin\x64\opengl32sw.dll"; DestDir: "{win}\system32"; Flags: ignoreversion 64bit; Check: IsWin64
Source: "..\bin\x64\swrAVX.dll"; DestDir: "{win}\system32"; Flags: ignoreversion 64bit; Check: IsWin64
Source: "..\bin\x64\swrAVX2.dll"; DestDir: "{win}\system32"; Flags: ignoreversion 64bit; Check: IsWin64
Source: "..\bin\x64\dxtn.dll"; DestDir: "{win}\system32"; Flags: ignoreversion 64bit; Check: IsWin64
Source: "..\localdeploy.cmd"; DestDir: "{app}"
; NOTE: Don't use "Flags: ignoreversion" on any shared system files

[Registry]
Root: "HKLM32"; Subkey: "SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL"; ValueType: string; ValueName: "DLL"; ValueData: "opengl32sw.dll"; Flags: createvalueifdoesntexist uninsdeletekey; Check: IsWin64
Root: "HKLM32"; Subkey: "SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL"; ValueType: dword; ValueName: "DriverVersion"; ValueData: "1"; Flags: createvalueifdoesntexist uninsdeletekey; Check: IsWin64
Root: "HKLM32"; Subkey: "SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL"; ValueType: dword; ValueName: "Flags"; ValueData: "1"; Flags: createvalueifdoesntexist uninsdeletekey; Check: IsWin64
Root: "HKLM32"; Subkey: "SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL"; ValueType: dword; ValueName: "Version"; ValueData: "2"; Flags: createvalueifdoesntexist uninsdeletekey; Check: IsWin64
Root: "HKLM"; Subkey: "SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL"; ValueType: string; ValueName: "DLL"; ValueData: "opengl32sw.dll"; Flags: createvalueifdoesntexist uninsdeletekey
Root: "HKLM"; Subkey: "SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL"; ValueType: dword; ValueName: "DriverVersion"; ValueData: "1"; Flags: createvalueifdoesntexist uninsdeletekey
Root: "HKLM"; Subkey: "SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL"; ValueType: dword; ValueName: "Flags"; ValueData: "1"; Flags: createvalueifdoesntexist uninsdeletekey
Root: "HKLM"; Subkey: "SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL"; ValueType: dword; ValueName: "Version"; ValueData: "2"; Flags: createvalueifdoesntexist uninsdeletekey

[UninstallDelete]
Type: files; Name: "{syswow64}\opengl32sw.dll"; Check: IsWin64
Type: files; Name: "{syswow64}\swrAVX.dll"; Check: IsWin64
Type: files; Name: "{syswow64}\swrAVX2.dll"; Check: IsWin64
Type: files; Name: "{syswow64}\cygwin1.dll"; Check: IsWin64
Type: files; Name: "{syswow64}\dxtn.dll"; Check: IsWin64
Type: files; Name: "{win}\system32\opengl32sw.dll"
Type: files; Name: "{win}\system32\swrAVX.dll"
Type: files; Name: "{win}\system32\swrAVX2.dll"
Type: files; Name: "{win}\system32\dxtn.dll"
Type: files; Name: "{win}\system32\cygwin1.dll"

[Icons]
Name: "{commondesktop}\Mesa3D local deployment utility"; Filename: "cmd"; Parameters: "/c ""{app}\localdeploy.cmd"""; AfterInstall: SetElevationBit ('{commondesktop}\Mesa3D local deployment utility.lnk')

[Code]

procedure SetElevationBit(Filename: string);
var
  Buffer: string;
  Stream: TStream;
begin
  Filename := ExpandConstant(Filename);
  Log('Setting elevation bit for ' + Filename);

  Stream := TFileStream.Create(FileName, fmOpenReadWrite);
  try
    Stream.Seek(21, soFromBeginning);
    SetLength(Buffer, 1);
    Stream.ReadBuffer(Buffer, 1);
    Buffer[1] := Chr(Ord(Buffer[1]) or $20);
    Stream.Seek(-1, soFromCurrent);
    Stream.WriteBuffer(Buffer, 1);
  finally
    Stream.Free;
  end;
end;

; Script generated by the Inno Script Studio Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

#define MyAppName "Mesa3D software rendering drivers for Windows"
#define MyAppVersion "17.0.1-3"
#define MyAppPublisher "Pal100x"
#define MyAppURL "https://github.com/pal1000/mesa-dist-win"
#define MyAppExeName "mesa-{#MyAppVersion}-setup.exe"

[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{8EFCCC7F-5BAF-4651-A040-EFB13C59EF60}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={pf64}\{#MyAppName}
LicenseFile=..\LICENSE
OutputDir=..\bin\
OutputBaseFilename=mesa-{#MyAppVersion}-setup
Compression=lzma
SolidCompression=yes

[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"

[Files]
Source: "..\bin\x86\opengl32sw.dll"; DestDir: "{win}\system32"; Flags: ignoreversion
Source: "..\bin\x86\swrAVX.dll"; DestDir: "{win}\system32"; Flags: ignoreversion
Source: "..\bin\x86\swrAVX2.dll"; DestDir: "{win}\system32"; Flags: ignoreversion
Source: "..\bin\x86\cygwin1.dll"; DestDir: "{win}\system32"; Flags: ignoreversion
Source: "..\bin\x86\dxtn.dll"; DestDir: "{win}\system32"; Flags: ignoreversion
Source: "..\bin\x64\opengl32sw.dll"; DestDir: "{win}\system32"; Flags: ignoreversion 64bit; Check: IsWin64
Source: "..\bin\x64\swrAVX.dll"; DestDir: "{win}\system32"; Flags: ignoreversion 64bit; Check: IsWin64
Source: "..\bin\x64\swrAVX2.dll"; DestDir: "{win}\system32"; Flags: ignoreversion 64bit; Check: IsWin64
Source: "..\bin\x64\dxtn.dll"; DestDir: "{win}\system32"; Flags: ignoreversion 64bit; Check: IsWin64
Source: "..\localdeploy.cmd"; DestDir: "{app}"
; NOTE: Don't use "Flags: ignoreversion" on any shared system files

[Registry]
Root: "HKLM32"; Subkey: "SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL"; ValueType: string; ValueName: "DLL"; ValueData: "opengl32sw.dll"; Flags: createvalueifdoesntexist uninsdeletekey; Check: IsWin64
Root: "HKLM32"; Subkey: "SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL"; ValueType: dword; ValueName: "DriverVersion"; ValueData: "1"; Flags: createvalueifdoesntexist uninsdeletekey; Check: IsWin64
Root: "HKLM32"; Subkey: "SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL"; ValueType: dword; ValueName: "Flags"; ValueData: "1"; Flags: createvalueifdoesntexist uninsdeletekey; Check: IsWin64
Root: "HKLM32"; Subkey: "SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL"; ValueType: dword; ValueName: "Version"; ValueData: "2"; Flags: createvalueifdoesntexist uninsdeletekey; Check: IsWin64
Root: "HKLM"; Subkey: "SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL"; ValueType: string; ValueName: "DLL"; ValueData: "opengl32sw.dll"; Flags: createvalueifdoesntexist uninsdeletekey
Root: "HKLM"; Subkey: "SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL"; ValueType: dword; ValueName: "DriverVersion"; ValueData: "1"; Flags: createvalueifdoesntexist uninsdeletekey
Root: "HKLM"; Subkey: "SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL"; ValueType: dword; ValueName: "Flags"; ValueData: "1"; Flags: createvalueifdoesntexist uninsdeletekey
Root: "HKLM"; Subkey: "SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL"; ValueType: dword; ValueName: "Version"; ValueData: "2"; Flags: createvalueifdoesntexist uninsdeletekey

[UninstallDelete]
Type: files; Name: "{syswow64}\opengl32sw.dll"; Check: IsWin64
Type: files; Name: "{syswow64}\swrAVX.dll"; Check: IsWin64
Type: files; Name: "{syswow64}\swrAVX2.dll"; Check: IsWin64
Type: files; Name: "{syswow64}\cygwin1.dll"; Check: IsWin64
Type: files; Name: "{syswow64}\dxtn.dll"; Check: IsWin64
Type: files; Name: "{win}\system32\opengl32sw.dll"
Type: files; Name: "{win}\system32\swrAVX.dll"
Type: files; Name: "{win}\system32\swrAVX2.dll"
Type: files; Name: "{win}\system32\dxtn.dll"
Type: files; Name: "{win}\system32\cygwin1.dll"

[Icons]
Name: "{commondesktop}\Mesa3D local deployment utility"; Filename: "cmd"; Parameters: "/c ""{app}\localdeploy.cmd"""; AfterInstall: SetElevationBit ('{commondesktop}\Mesa3D local deployment utility.lnk')

[Code]

procedure SetElevationBit(Filename: string);
var
  Buffer: string;
  Stream: TStream;
begin
  Filename := ExpandConstant(Filename);
  Log('Setting elevation bit for ' + Filename);

  Stream := TFileStream.Create(FileName, fmOpenReadWrite);
  try
    Stream.Seek(21, soFromBeginning);
    SetLength(Buffer, 1);
    Stream.ReadBuffer(Buffer, 1);
    Buffer[1] := Chr(Ord(Buffer[1]) or $20);
    Stream.Seek(-1, soFromCurrent);
    Stream.WriteBuffer(Buffer, 1);
  finally
    Stream.Free;
  end;
end;


Release 17.1.4.401-1

Release 17.1.4.401-1

; Script generated by the Inno Script Studio Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

#define MyAppName "Mesa3D software rendering drivers for Windows"
#define MyAppVersion "17.1.4.401-1"
#define MyAppPublisher "Pal100x"
#define MyAppURL "https://github.com/pal1000/mesa-dist-win"
#define MyAppExeName "mesa-{#MyAppVersion}-setup.exe"

[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{8EFCCC7F-5BAF-4651-A040-EFB13C59EF60}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
ArchitecturesInstallIn64BitMode=x64
DefaultDirName={pf}\{#MyAppName}
DisableProgramGroupPage=yes
LicenseFile=LICENSE
OutputDir=bin\
OutputBaseFilename=mesa-{#MyAppVersion}-setup
Compression=lzma
SolidCompression=yes

[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"

[Files]
Source: "bin\x86\opengl32.dll"; DestDir: "{app}\x86"; Flags: ignoreversion
Source: "bin\x86\swrAVX.dll"; DestDir: "{app}\x86"; Flags: ignoreversion
Source: "bin\x86\swrAVX2.dll"; DestDir: "{app}\x86"; Flags: ignoreversion
Source: "bin\x86\dxtn.dll"; DestDir: "{app}\x86"; Flags: ignoreversion
Source: "bin\x86\osmesa-gallium.dll"; DestDir: "{app}\x86"; Flags: ignoreversion
Source: "bin\x86\osmesa-swrast.dll"; DestDir: "{app}\x86"; Flags: ignoreversion
Source: "bin\x86\graw.dll"; DestDir: "{app}\x86"; Flags: ignoreversion
Source: "bin\x64\opengl32.dll"; DestDir: "{app}\x64"; Flags: ignoreversion; Check: Is64BitInstallMode
Source: "bin\x64\swrAVX.dll"; DestDir: "{app}\x64"; Flags: ignoreversion; Check: Is64BitInstallMode
Source: "bin\x64\swrAVX2.dll"; DestDir: "{app}\x64"; Flags: ignoreversion; Check: Is64BitInstallMode
Source: "bin\x64\dxtn.dll"; DestDir: "{app}\x64"; Flags: ignoreversion; Check: Is64BitInstallMode
Source: "bin\x64\osmesa-gallium.dll"; DestDir: "{app}\x64"; Flags: ignoreversion; Check: Is64BitInstallMode
Source: "bin\x64\osmesa-swrast.dll"; DestDir: "{app}\x64"; Flags: ignoreversion; Check: Is64BitInstallMode
Source: "bin\x64\graw.dll"; DestDir: "{app}\x64"; Flags: ignoreversion; Check: Is64BitInstallMode
Source: "bin\quickdeploy.cmd"; DestDir: "{app}"
Source: "bin\readme.txt"; DestDir: "{app}"

; NOTE: Don't use "Flags: ignoreversion" on any shared system files

[UninstallDelete]
Type: files; Name: "{app}\x86\opengl32.dll"
Type: files; Name: "{app}\x86\swrAVX.dll";
Type: files; Name: "{app}\x86\swrAVX2.dll"
Type: files; Name: "{app}\x86\dxtn.dll"
Type: files; Name: "{app}\x86\graw.dll";
Type: files; Name: "{app}\x86\osmesa-gallium.dll"
Type: files; Name: "{app}\x86\osmesa-swrast.dll"
Type: files; Name: "{app}\x64\opengl32.dll"; Check: Is64BitInstallMode
Type: files; Name: "{app}\x64\swrAVX.dll"; Check: Is64BitInstallMode
Type: files; Name: "{app}\x64\swrAVX2.dll"; Check: Is64BitInstallMode
Type: files; Name: "{app}\x64\dxtn.dll"; Check: Is64BitInstallMode
Type: files; Name: "{app}\x64\osmesa-gallium.dll"; Check: Is64BitInstallMode
Type: files; Name: "{app}\x64\osmesa-swrast.dll"; Check: Is64BitInstallMode
Type: files; Name: "{app}\x64\graw.dll"; Check: Is64BitInstallMode
Type: files; Name: "{app}\quickdeploy.cmd"
Type: files; Name: "{app}\readme.txt"

[Icons]
Name: "{commondesktop}\Mesa3D quick deployment utility"; Filename: "{app}\quickdeploy.cmd"

[Run]
Filename: "{app}\readme.txt"; Description: "View the README file"; Flags: postinstall shellexec skipifsilent

; Script generated by the Inno Script Studio Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

#define MyAppName "Mesa3D software rendering drivers for Windows"
#define MyAppVersion "17.1.4.400-1"
#define MyAppPublisher "Pal100x"
#define MyAppURL "https://github.com/pal1000/mesa-dist-win"
#define MyAppExeName "mesa-{#MyAppVersion}-setup.exe"

[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{8EFCCC7F-5BAF-4651-A040-EFB13C59EF60}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
ArchitecturesInstallIn64BitMode=x64
DefaultDirName={pf}\{#MyAppName}
DisableProgramGroupPage=yes
LicenseFile=LICENSE
OutputDir=bin\
OutputBaseFilename=mesa-{#MyAppVersion}-setup
Compression=lzma
SolidCompression=yes

[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"

[Files]
Source: "bin\x86\opengl32.dll"; DestDir: "{app}\x86"; Flags: ignoreversion
Source: "bin\x86\swrAVX.dll"; DestDir: "{app}\x86"; Flags: ignoreversion
Source: "bin\x86\swrAVX2.dll"; DestDir: "{app}\x86"; Flags: ignoreversion
Source: "bin\x86\dxtn.dll"; DestDir: "{app}\x86"; Flags: ignoreversion
Source: "bin\x86\osmesa-gallium.dll"; DestDir: "{app}\x86"; Flags: ignoreversion
Source: "bin\x86\osmesa-swrast.dll"; DestDir: "{app}\x86"; Flags: ignoreversion
Source: "bin\x86\graw.dll"; DestDir: "{app}\x86"; Flags: ignoreversion
Source: "bin\x64\opengl32.dll"; DestDir: "{app}\x64"; Flags: ignoreversion; Check: Is64BitInstallMode
Source: "bin\x64\swrAVX.dll"; DestDir: "{app}\x64"; Flags: ignoreversion; Check: Is64BitInstallMode
Source: "bin\x64\swrAVX2.dll"; DestDir: "{app}\x64"; Flags: ignoreversion; Check: Is64BitInstallMode
Source: "bin\x64\dxtn.dll"; DestDir: "{app}\x64"; Flags: ignoreversion; Check: Is64BitInstallMode
Source: "bin\x64\osmesa-gallium.dll"; DestDir: "{app}\x64"; Flags: ignoreversion; Check: Is64BitInstallMode
Source: "bin\x64\osmesa-swrast.dll"; DestDir: "{app}\x64"; Flags: ignoreversion; Check: Is64BitInstallMode
Source: "bin\x64\graw.dll"; DestDir: "{app}\x64"; Flags: ignoreversion; Check: Is64BitInstallMode
Source: "bin\quickdeploy.cmd"; DestDir: "{app}"
Source: "bin\readme.txt"; DestDir: "{app}"

; NOTE: Don't use "Flags: ignoreversion" on any shared system files

[UninstallDelete]
Type: files; Name: "{app}\x86\opengl32.dll"
Type: files; Name: "{app}\x86\swrAVX.dll";
Type: files; Name: "{app}\x86\swrAVX2.dll"
Type: files; Name: "{app}\x86\dxtn.dll"
Type: files; Name: "{app}\x86\graw.dll";
Type: files; Name: "{app}\x86\osmesa-gallium.dll"
Type: files; Name: "{app}\x86\osmesa-swrast.dll"
Type: files; Name: "{app}\x64\opengl32.dll"; Check: Is64BitInstallMode
Type: files; Name: "{app}\x64\swrAVX.dll"; Check: Is64BitInstallMode
Type: files; Name: "{app}\x64\swrAVX2.dll"; Check: Is64BitInstallMode
Type: files; Name: "{app}\x64\dxtn.dll"; Check: Is64BitInstallMode
Type: files; Name: "{app}\x64\osmesa-gallium.dll"; Check: Is64BitInstallMode
Type: files; Name: "{app}\x64\osmesa-swrast.dll"; Check: Is64BitInstallMode
Type: files; Name: "{app}\x64\graw.dll"; Check: Is64BitInstallMode
Type: files; Name: "{app}\quickdeploy.cmd"
Type: files; Name: "{app}\readme.txt"

[Icons]
Name: "{commondesktop}\Mesa3D quick deployment utility"; Filename: "{app}\quickdeploy.cmd"

[Run]
Filename: "{app}\readme.txt"; Description: "View the README file"; Flags: postinstall shellexec skipifsilent


Update config.yml for current user installation

; RailsInstaller - InnoSetup Script
; Adaptation from RubyInstaller installer script
;

; PRE-CHECK
; Verify that RubyPath is defined by ISCC using
; /d command line arguments.
;
; Usage:
;  iscc rubyinstaller.iss /dInstallerVersion=0.1.0
;                         /dStagePath=stage
;                         /dRubyPath=Ruby/1.8.7
;                         [/dInstVersion=26-OCT-2009]

; Full example:
; iscc resouces\railsinstaller\railsinstaller.iss \
;       /dInstallerVersion=0.1.0 \
;       /dStagePath=stage \
;       /dRubyPath=Ruby1.8.7 \
;       /opkg
;       /frailsinstaller-0.1.0.exe

#if Defined(InstallerVersion) == 0
  #error Please provide a InstallerVersion definition using a /d parameter.
#endif

#if Defined(StagePath) == 0
  #error Please provide a StagePath value to the Ruby files using a /d parameter.
#endif

#if Defined(RubyPath) == 0
  #error Please provide a RubyPath value to the Ruby files using a /d parameter.
#else
  #if FileExists(StagePath + '/' + RubyPath + '\bin\ruby.exe') == 0
    #error No Ruby installation (bin\ruby.exe) found inside defined RubyPath. Please verify.
  #endif
#endif

#if Defined(InstVersion) == 0
  #define InstVersion GetDateTimeString('dd-mmm-yy"T"hhnn', '', '')
#endif

; Build Installer details using above values
#define InstallerName "RailsInstaller " + InstallerVersion
#define InstallerPublisher "RailsInstaller Team"
#define InstallerHomepage "http://www.railsinstaller.org/"

#define CurrentYear GetDateTimeString('yyyy', '', '')

[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications!
AppId={{613C3EA5-1248-4E35-B61A-6D0B31BBC0DB}
AppName={#InstallerName}
AppVerName={#InstallerName}
AppPublisher={#InstallerPublisher}
AppPublisherURL={#InstallerHomepage}
AppVersion={#InstallerVersion}
DefaultGroupName={#InstallerName}
DefaultDirName={sd}\RailsInstaller
DisableProgramGroupPage=true
LicenseFile=LICENSE.txt
Compression=lzma2/ultra64
SolidCompression=true
AlwaysShowComponentsList=false
DisableReadyPage=true
InternalCompressLevel=ultra64
VersionInfoCompany={#InstallerPublisher}
VersionInfoCopyright=(c) {#CurrentYear} {#InstallerPublisher}
VersionInfoDescription=Rails development environment installer for Windows
VersionInfoTextVersion={#InstallerVersion}
VersionInfoVersion={#InstallerVersion}
UninstallDisplayIcon={app}\bin\ruby.exe
WizardImageFile=compiler:wizmodernimage-is.bmp
WizardSmallImageFile=compiler:wizmodernsmallimage-is.bmp
PrivilegesRequired=lowest
ChangesAssociations=yes
ChangesEnvironment=yes

#if Defined(SignPackage) == 1
SignTool=risigntool sign /a /d $q{#InstallerName}$q /du $q{#InstallerHomepage}$q /t $qhttp://timestamp.comodoca.com/authenticode$q $f
#endif

[Languages]
Name: en; MessagesFile: compiler:Default.isl

[Messages]
en.InstallingLabel=Installing [name], this may take a few minutes...
en.WelcomeLabel1=Welcome to the [name] Installer
en.WelcomeLabel2=This will install [name/ver] on your computer. This will install Ruby 1.8.7, Git, Sqlite3, DevKit, and Rails 3. Your PATH will be modified so that when you start a console process ruby, git and rails are all available to you. Please close any console applications before continuing.
en.WizardLicense={#InstallerName} License Agreement
en.LicenseLabel=
en.LicenseLabel3=Please read the following License Agreements and accept the terms before continuing the installation.
en.LicenseAccepted=I &accept all of the Licenses
en.LicenseNotAccepted=I &decline any of the Licenses
en.WizardSelectDir=Installation Destination and Optional Tasks
en.SelectDirDesc=
en.SelectDirLabel3=Setup will install [name] into the following folder. Click Install to continue or click Browse to use a different one.
en.SelectDirBrowseLabel=Please avoid any folder name that contains spaces (e.g. Program Files).
en.DiskSpaceMBLabel=Required free disk space: ~[mb] MB

[Files]
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
Source: {#StagePath}\{#RubyPath}\*; DestDir: {app}\{#RubyPath}; Flags: recursesubdirs createallsubdirs
Source: {#StagePath}\Git\*; DestDir: {app}\Git; Flags: recursesubdirs createallsubdirs
Source: {#StagePath}\DevKit\*; DestDir: {app}\DevKit; Excludes: config.yml Flags: recursesubdirs createallsubdirs
Source: {#StagePath}\DevKit\config.yml; DestDir: {app}\DevKit; AfterInstall: UpdateDevKitConfig('{app}\{#RubyPath}', '{app}\DevKit\config.yml')
Source: {#StagePath}\Sites\*; DestDir: {app}\Sites; Flags: recursesubdirs createallsubdirs
Source: setup_environment.bat; DestDir: {app}\{#RubyPath}

[Registry]
; FIXME: Proper registry keys for RailsInstaller (admin)
;Root: HKLM; Subkey: Software\RailsInstaller; ValueType: string; ValueName: ; ValueData: ; Flags: uninsdeletevalue uninsdeletekeyifempty; Check: IsAdmin

; FIXME: Proper registry key for RailsInstaller (user)
;Root: HKCU; Subkey: Software\RailsInstaller; ValueType: string; ValueName: ; ValueData: ; Flags: uninsdeletevalue uninsdeletekeyifempty; Check: IsNotAdmin

[Icons]
Name: {group}\Interactive Ruby; Filename: {app}\{#RubyPath}\bin\irb.bat; IconFilename: {app}\{#RubyPath}\bin\ruby.exe; Flags: createonlyiffileexists
Name: {group}\RubyGems Documentation Server; Filename: {app}\{#RubyPath}\bin\gem.bat; Parameters: server; IconFilename: {app}\{#RubyPath}\bin\ruby.exe; Flags: createonlyiffileexists runminimized
Name: {group}\Start Command Prompt with Ruby and Rails; Filename: {sys}\cmd.exe; Parameters: /E:ON /K {app}\{#RubyPath}\setup_environment.bat; WorkingDir: {%HOMEDRIVE}{%HOMEPATH}; IconFilename: {sys}\cmd.exe; Flags: createonlyiffileexists
Name: {group}\{cm:UninstallProgram,{#InstallerName}}; Filename: {uninstallexe}

[Code]
#include "util.iss"
#include "railsinstaller_gui.iss"

function GetInstallDate(Param: String): String;
begin
  Result := GetDateTimeString('yyyymmdd', #0 , #0);
end;

procedure CurStepChanged(const CurStep: TSetupStep);
begin

  // TODO move into ssPostInstall just after install completes?
  if CurStep = ssInstall then
  begin
    if UsingWinNT then
    begin
      Log(Format('Selected Tasks - Path: %d', [PathChkBox.State]));

      if IsModifyPath then
        ModifyPath([ExpandConstant('{app}') + '\{#RubyPath}\bin']);
        ModifyPath([ExpandConstant('{app}') + '\Git\cmd']);

    end else
      MsgBox('Looks like you''ve got on older, unsupported Windows version.' #13 +
             'Proceeding with a reduced feature set installation.',
             mbInformation, MB_OK);
  end;
end;

procedure RegisterPreviousData(PreviousDataKey: Integer);
begin
  {* store install choices so we can use during uninstall *}
  if IsModifyPath then
    SetPreviousData(PreviousDataKey, 'PathModified', 'yes');

  SetPreviousData(PreviousDataKey, 'RailsInstallerId', '{#InstallerVersion}');
end;

procedure CurUninstallStepChanged(const CurUninstallStep: TUninstallStep);
begin
  if CurUninstallStep = usUninstall then
  begin
    if UsingWinNT then
    begin
      if GetPreviousData('PathModified', 'no') = 'yes' then
        ModifyPath([ExpandConstant('{app}') + '\{#RubyPath}\bin']);
        ModifyPath([ExpandConstant('{app}') + '\Git\cmd']);
    end;
  end;
end;

procedure UpdateDevKitConfig(RubyPath: string; FileName: string);
var
  S: String;
begin
  // Make YAML happy :-)
  S := ExpandConstant(RubyPath);
  StringChangeEx(S, '\', '/', True);

  // Update DevKit config.yml with the installation path
  SaveStringToFile(ExpandConstant(FileName), '- ' + S, False);
end;

; RailsInstaller - InnoSetup Script
; Adaptation from RubyInstaller installer script
;

; PRE-CHECK
; Verify that RubyPath is defined by ISCC using
; /d command line arguments.
;
; Usage:
;  iscc rubyinstaller.iss /dInstallerVersion=0.1.0
;                         /dStagePath=stage
;                         /dRubyPath=Ruby/1.8.7
;                         [/dInstVersion=26-OCT-2009]

; Full example:
; iscc resouces\railsinstaller\railsinstaller.iss \
;       /dInstallerVersion=0.1.0 \
;       /dStagePath=stage \
;       /dRubyPath=Ruby1.8.7 \
;       /opkg
;       /frailsinstaller-0.1.0.exe

#if Defined(InstallerVersion) == 0
  #error Please provide a InstallerVersion definition using a /d parameter.
#endif

#if Defined(StagePath) == 0
  #error Please provide a StagePath value to the Ruby files using a /d parameter.
#endif

#if Defined(RubyPath) == 0
  #error Please provide a RubyPath value to the Ruby files using a /d parameter.
#else
  #if FileExists(StagePath + '/' + RubyPath + '\bin\ruby.exe') == 0
    #error No Ruby installation (bin\ruby.exe) found inside defined RubyPath. Please verify.
  #endif
#endif

#if Defined(InstVersion) == 0
  #define InstVersion GetDateTimeString('dd-mmm-yy"T"hhnn', '', '')
#endif

; Build Installer details using above values
#define InstallerName "RailsInstaller " + InstallerVersion
#define InstallerPublisher "RailsInstaller Team"
#define InstallerHomepage "http://www.railsinstaller.org/"

#define CurrentYear GetDateTimeString('yyyy', '', '')

[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications!
AppId={{613C3EA5-1248-4E35-B61A-6D0B31BBC0DB}
AppName={#InstallerName}
AppVerName={#InstallerName}
AppPublisher={#InstallerPublisher}
AppPublisherURL={#InstallerHomepage}
AppVersion={#InstallerVersion}
DefaultGroupName={#InstallerName}
DefaultDirName={sd}\RailsInstaller
DisableProgramGroupPage=true
LicenseFile=LICENSE.txt
Compression=lzma2/ultra64
SolidCompression=true
AlwaysShowComponentsList=false
DisableReadyPage=true
InternalCompressLevel=ultra64
VersionInfoCompany={#InstallerPublisher}
VersionInfoCopyright=(c) {#CurrentYear} {#InstallerPublisher}
VersionInfoDescription=Rails development environment installer for Windows
VersionInfoTextVersion={#InstallerVersion}
VersionInfoVersion={#InstallerVersion}
UninstallDisplayIcon={app}\bin\ruby.exe
WizardImageFile=compiler:wizmodernimage-is.bmp
WizardSmallImageFile=compiler:wizmodernsmallimage-is.bmp
PrivilegesRequired=lowest
ChangesAssociations=yes
ChangesEnvironment=yes

#if Defined(SignPackage) == 1
SignTool=risigntool sign /a /d $q{#InstallerName}$q /du $q{#InstallerHomepage}$q /t $qhttp://timestamp.comodoca.com/authenticode$q $f
#endif

[Languages]
Name: en; MessagesFile: compiler:Default.isl

[Messages]
en.InstallingLabel=Installing [name], this may take a few minutes...
en.WelcomeLabel1=Welcome to the [name] Installer
en.WelcomeLabel2=This will install [name/ver] on your computer. This will install Ruby 1.8.7, Git, Sqlite3, DevKit, and Rails 3. Your PATH will be modified so that when you start a console process ruby, git and rails are all available to you. Please close any console applications before continuing.
en.WizardLicense={#InstallerName} License Agreement
en.LicenseLabel=
en.LicenseLabel3=Please read the following License Agreements and accept the terms before continuing the installation.
en.LicenseAccepted=I &accept all of the Licenses
en.LicenseNotAccepted=I &decline any of the Licenses
en.WizardSelectDir=Installation Destination and Optional Tasks
en.SelectDirDesc=
en.SelectDirLabel3=Setup will install [name] into the following folder. Click Install to continue or click Browse to use a different one.
en.SelectDirBrowseLabel=Please avoid any folder name that contains spaces (e.g. Program Files).
en.DiskSpaceMBLabel=Required free disk space: ~[mb] MB

[Files]
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
Source: {#StagePath}\{#RubyPath}\*; DestDir: {app}\{#RubyPath}; Flags: recursesubdirs createallsubdirs
Source: {#StagePath}\Git\*; DestDir: {app}\Git; Flags: recursesubdirs createallsubdirs
Source: {#StagePath}\DevKit\*; DestDir: {app}\DevKit; Flags: recursesubdirs createallsubdirs
Source: {#StagePath}\Sites\*; DestDir: {app}\Sites; Flags: recursesubdirs createallsubdirs
Source: setup_environment.bat; DestDir: {app}\{#RubyPath}

[Registry]
; FIXME: Proper registry keys for RailsInstaller (admin)
;Root: HKLM; Subkey: Software\RailsInstaller; ValueType: string; ValueName: ; ValueData: ; Flags: uninsdeletevalue uninsdeletekeyifempty; Check: IsAdmin

; FIXME: Proper registry key for RailsInstaller (user)
;Root: HKCU; Subkey: Software\RailsInstaller; ValueType: string; ValueName: ; ValueData: ; Flags: uninsdeletevalue uninsdeletekeyifempty; Check: IsNotAdmin

[Icons]
Name: {group}\Interactive Ruby; Filename: {app}\{#RubyPath}\bin\irb.bat; IconFilename: {app}\{#RubyPath}\bin\ruby.exe; Flags: createonlyiffileexists
Name: {group}\RubyGems Documentation Server; Filename: {app}\{#RubyPath}\bin\gem.bat; Parameters: server; IconFilename: {app}\{#RubyPath}\bin\ruby.exe; Flags: createonlyiffileexists runminimized
Name: {group}\Start Command Prompt with Ruby and Rails; Filename: {sys}\cmd.exe; Parameters: /E:ON /K {app}\{#RubyPath}\setup_environment.bat; WorkingDir: {%HOMEDRIVE}{%HOMEPATH}; IconFilename: {sys}\cmd.exe; Flags: createonlyiffileexists
Name: {group}\{cm:UninstallProgram,{#InstallerName}}; Filename: {uninstallexe}

[Code]
#include "util.iss"
#include "railsinstaller_gui.iss"

function GetInstallDate(Param: String): String;
begin
  Result := GetDateTimeString('yyyymmdd', #0 , #0);
end;

procedure CurStepChanged(const CurStep: TSetupStep);
begin

  // TODO move into ssPostInstall just after install completes?
  if CurStep = ssInstall then
  begin
    if UsingWinNT then
    begin
      Log(Format('Selected Tasks - Path: %d', [PathChkBox.State]));

      if IsModifyPath then
        ModifyPath([ExpandConstant('{app}') + '\{#RubyPath}\bin']);
        ModifyPath([ExpandConstant('{app}') + '\Git\cmd']);

    end else
      MsgBox('Looks like you''ve got on older, unsupported Windows version.' #13 +
             'Proceeding with a reduced feature set installation.',
             mbInformation, MB_OK);
  end;
end;

procedure RegisterPreviousData(PreviousDataKey: Integer);
begin
  {* store install choices so we can use during uninstall *}
  if IsModifyPath then
    SetPreviousData(PreviousDataKey, 'PathModified', 'yes');

  SetPreviousData(PreviousDataKey, 'RailsInstallerId', '{#InstallerVersion}');
end;

procedure CurUninstallStepChanged(const CurUninstallStep: TUninstallStep);
begin
  if CurUninstallStep = usUninstall then
  begin
    if UsingWinNT then
    begin
      if GetPreviousData('PathModified', 'no') = 'yes' then
        ModifyPath([ExpandConstant('{app}') + '\{#RubyPath}\bin']);
        ModifyPath([ExpandConstant('{app}') + '\Git\cmd']);
    end;
  end;
end;


Corrected the setvars.bat shortcut.

Corrected the setvars.bat shortcut.

; RailsInstaller - InnoSetup Script
; Adaptation from RubyInstaller installer script
;

; PRE-CHECK
; Verify that RubyPath is defined by ISCC using
; /d command line arguments.
;
; Usage:
;  iscc rubyinstaller.iss /dInstallerVersion=0.1.0
;                         /dStagePath=stage
;                         /dRubyPath=Ruby/1.8.7
;                         [/dInstVersion=26-OCT-2009]

; Full example:
; iscc resouces\railsinstaller\railsinstaller.iss \
;       /dInstallerVersion=0.1.0 \
;       /dStagePath=stage \
;       /dRubyPath=Ruby1.8.7 \
;       /opkg
;       /frailsinstaller-0.1.0.exe

#if Defined(InstallerVersion) == 0
  #error Please provide a InstallerVersion definition using a /d parameter.
#endif

#if Defined(StagePath) == 0
  #error Please provide a StagePath value to the Ruby files using a /d parameter.
#endif

#if Defined(RubyPath) == 0
  #error Please provide a RubyPath value to the Ruby files using a /d parameter.
#else
  #if FileExists(StagePath + '/' + RubyPath + '\bin\ruby.exe') == 0
    #error No Ruby installation (bin\ruby.exe) found inside defined RubyPath. Please verify.
  #endif
#endif

#if Defined(InstVersion) == 0
  #define InstVersion GetDateTimeString('dd-mmm-yy"T"hhnn', '', '')
#endif

; Build Installer details using above values
#define InstallerName "RailsInstaller " + InstallerVersion
#define InstallerPublisher "RailsInstaller Team"
#define InstallerHomepage "http://www.railsinstaller.org"

#define CurrentYear GetDateTimeString('yyyy', '', '')

[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications!
AppId={{613C3EA5-1248-4E35-B61A-6D0B31BBC0DB}
AppName={#InstallerName}
AppVerName={#InstallerName}
AppPublisher={#InstallerPublisher}
AppPublisherURL={#InstallerHomepage}
AppVersion={#InstallerVersion}
DefaultGroupName={#InstallerName}
DefaultDirName={sd}\RailsInstaller
DisableProgramGroupPage=true
LicenseFile=LICENSE
Compression=lzma2/ultra64
SolidCompression=true
AlwaysShowComponentsList=false
DisableReadyPage=true
InternalCompressLevel=ultra64
VersionInfoCompany={#InstallerPublisher}
VersionInfoCopyright=(c) {#CurrentYear} {#InstallerPublisher}
VersionInfoDescription=Rails development environment installer for Windows
VersionInfoTextVersion={#InstallerVersion}
VersionInfoVersion={#InstallerVersion}
UninstallDisplayIcon={app}\bin\ruby.exe
WizardImageFile=compiler:wizmodernimage-is.bmp
WizardSmallImageFile=compiler:wizmodernsmallimage-is.bmp
PrivilegesRequired=lowest
ChangesAssociations=yes
ChangesEnvironment=yes

#if Defined(SignPackage) == 1
SignTool=risigntool sign /a /d $q{#InstallerName}$q /du $q{#InstallerHomepage}$q /t $qhttp://timestamp.comodoca.com/authenticode$q $f
#endif

[Languages]
Name: en; MessagesFile: compiler:Default.isl

[Messages]
en.WelcomeLabel1=Welcome to the [name] Installer
en.WelcomeLabel2=This will install [name/ver] on your computer. Please close all other applications before continuing.
en.WizardLicense={#InstallerName} License Agreement
en.LicenseLabel=
en.LicenseLabel3=Please read the following License Agreement and accept the terms before continuing the installation.
en.LicenseAccepted=I &accept the License
en.LicenseNotAccepted=I &decline the License
en.WizardSelectDir=Installation Destination and Optional Tasks
en.SelectDirDesc=
en.SelectDirLabel3=Setup will install [name] into the following folder. Click Install to continue or click Browse to use a different one.
en.SelectDirBrowseLabel=Please avoid any folder name that contains spaces (e.g. Program Files).
en.DiskSpaceMBLabel=Required free disk space: ~[mb] MB

[Files]
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
Source: ..\..\{#StagePath}\{#RubyPath}\*; DestDir: {app}\{#RubyPath}; Flags: recursesubdirs createallsubdirs
Source: ..\..\{#StagePath}\Git\*; DestDir: {app}\Git; Flags: recursesubdirs createallsubdirs
Source: ..\..\{#StagePath}\DevKit\*; DestDir: {app}\DevKit; Flags: recursesubdirs createallsubdirs
Source: setvars.bat; DestDir: {app}

[Registry]
; RubyInstaller identification for admin
; FIXME: Proper registry keys for RailsInstaller (admin)
;Root: HKLM; Subkey: Software\RailsInstaller; ValueType: string; ValueName: ; ValueData: ; Flags: uninsdeletevalue uninsdeletekeyifempty; Check: IsAdmin

; RubyInstaller identification for non-admin
; FIXME: Proper registry key for RailsInstaller (user)
;Root: HKCU; Subkey: Software\RailsInstaller; ValueType: string; ValueName: ; ValueData: ; Flags: uninsdeletevalue uninsdeletekeyifempty; Check: IsNotAdmin

[Icons]
Name: {group}\Interactive Ruby; Filename: {app}\{#RubyPath}\bin\irb.bat; IconFilename: {app}\{#RubyPath}\bin\ruby.exe; Flags: createonlyiffileexists
Name: {group}\RubyGems Documentation Server; Filename: {app}\{#RubyPath}\bin\gem.bat; Parameters: server; IconFilename: {app}\{#RubyPath}\bin\ruby.exe; Flags: createonlyiffileexists runminimized
Name: {group}\Start Command Prompt with RailsInstaller; Filename: {sys}\cmd.exe; Parameters: /E:ON /K {app}\setvars.bat; WorkingDir: {%HOMEDRIVE}{%HOMEPATH}; IconFilename: {sys}\cmd.exe; Flags: createonlyiffileexists
Name: {group}\{cm:UninstallProgram,{#InstallerName}}; Filename: {uninstallexe}

[Code]
#include "util.iss"
#include "railsinstaller_gui.iss"

function GetInstallDate(Param: String): String;
begin
  Result := GetDateTimeString('yyyymmdd', #0 , #0);
end;

procedure CurStepChanged(const CurStep: TSetupStep);
begin

  // TODO move into ssPostInstall just after install completes?
  if CurStep = ssInstall then
  begin
    if UsingWinNT then
    begin
      Log(Format('Selected Tasks - Path: %d', [PathChkBox.State]));

      if IsModifyPath then
        ModifyPath([ExpandConstant('{app}') + '\{#RubyPath}\bin']);
        ModifyPath([ExpandConstant('{app}') + '\Git\cmd']);

    end else
      MsgBox('Looks like you''ve got on older, unsupported Windows version.' #13 +
             'Proceeding with a reduced feature set installation.',
             mbInformation, MB_OK);
  end;
end;

procedure RegisterPreviousData(PreviousDataKey: Integer);
begin
  {* store install choices so we can use during uninstall *}
  if IsModifyPath then
    SetPreviousData(PreviousDataKey, 'PathModified', 'yes');

  SetPreviousData(PreviousDataKey, 'RailsInstallerId', '{#InstallerVersion}');
end;

procedure CurUninstallStepChanged(const CurUninstallStep: TUninstallStep);
begin
  if CurUninstallStep = usUninstall then
  begin
    if UsingWinNT then
    begin
      if GetPreviousData('PathModified', 'no') = 'yes' then
        ModifyPath([ExpandConstant('{app}') + '\{#RubyPath}\bin']);
        ModifyPath([ExpandConstant('{app}') + '\Git\cmd']);
    end;
  end;
end;

; RailsInstaller - InnoSetup Script
; Adaptation from RubyInstaller installer script
;

; PRE-CHECK
; Verify that RubyPath is defined by ISCC using
; /d command line arguments.
;
; Usage:
;  iscc rubyinstaller.iss /dInstallerVersion=0.1.0
;                         /dStagePath=stage
;                         /dRubyPath=Ruby/1.8.7
;                         [/dInstVersion=26-OCT-2009]

; Full example:
; iscc resouces\railsinstaller\railsinstaller.iss \
;       /dInstallerVersion=0.1.0 \
;       /dStagePath=stage \
;       /dRubyPath=Ruby1.8.7 \
;       /opkg
;       /frailsinstaller-0.1.0.exe

#if Defined(InstallerVersion) == 0
  #error Please provide a InstallerVersion definition using a /d parameter.
#endif

#if Defined(StagePath) == 0
  #error Please provide a StagePath value to the Ruby files using a /d parameter.
#endif

#if Defined(RubyPath) == 0
  #error Please provide a RubyPath value to the Ruby files using a /d parameter.
#else
  #if FileExists(StagePath + '/' + RubyPath + '\bin\ruby.exe') == 0
    #error No Ruby installation (bin\ruby.exe) found inside defined RubyPath. Please verify.
  #endif
#endif

#if Defined(InstVersion) == 0
  #define InstVersion GetDateTimeString('dd-mmm-yy"T"hhnn', '', '')
#endif

; Build Installer details using above values
#define InstallerName "RailsInstaller " + InstallerVersion
#define InstallerPublisher "RailsInstaller Team"
#define InstallerHomepage "http://www.railsinstaller.org"

#define CurrentYear GetDateTimeString('yyyy', '', '')

[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications!
AppId={{613C3EA5-1248-4E35-B61A-6D0B31BBC0DB}
AppName={#InstallerName}
AppVerName={#InstallerName}
AppPublisher={#InstallerPublisher}
AppPublisherURL={#InstallerHomepage}
AppVersion={#InstallerVersion}
DefaultGroupName={#InstallerName}
DefaultDirName={sd}\RailsInstaller
DisableProgramGroupPage=true
LicenseFile=LICENSE
Compression=lzma2/ultra64
SolidCompression=true
AlwaysShowComponentsList=false
DisableReadyPage=true
InternalCompressLevel=ultra64
VersionInfoCompany={#InstallerPublisher}
VersionInfoCopyright=(c) {#CurrentYear} {#InstallerPublisher}
VersionInfoDescription=Rails development environment installer for Windows
VersionInfoTextVersion={#InstallerVersion}
VersionInfoVersion={#InstallerVersion}
UninstallDisplayIcon={app}\bin\ruby.exe
WizardImageFile=compiler:wizmodernimage-is.bmp
WizardSmallImageFile=compiler:wizmodernsmallimage-is.bmp
PrivilegesRequired=lowest
ChangesAssociations=yes
ChangesEnvironment=yes

#if Defined(SignPackage) == 1
SignTool=risigntool sign /a /d $q{#InstallerName}$q /du $q{#InstallerHomepage}$q /t $qhttp://timestamp.comodoca.com/authenticode$q $f
#endif

[Languages]
Name: en; MessagesFile: compiler:Default.isl

[Messages]
en.WelcomeLabel1=Welcome to the [name] Installer
en.WelcomeLabel2=This will install [name/ver] on your computer. Please close all other applications before continuing.
en.WizardLicense={#InstallerName} License Agreement
en.LicenseLabel=
en.LicenseLabel3=Please read the following License Agreement and accept the terms before continuing the installation.
en.LicenseAccepted=I &accept the License
en.LicenseNotAccepted=I &decline the License
en.WizardSelectDir=Installation Destination and Optional Tasks
en.SelectDirDesc=
en.SelectDirLabel3=Setup will install [name] into the following folder. Click Install to continue or click Browse to use a different one.
en.SelectDirBrowseLabel=Please avoid any folder name that contains spaces (e.g. Program Files).
en.DiskSpaceMBLabel=Required free disk space: ~[mb] MB

[Files]
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
Source: ..\..\{#StagePath}\{#RubyPath}\*; DestDir: {app}\{#RubyPath}; Flags: recursesubdirs createallsubdirs
Source: ..\..\{#StagePath}\Git\*; DestDir: {app}\Git; Flags: recursesubdirs createallsubdirs
Source: ..\..\{#StagePath}\DevKit\*; DestDir: {app}\DevKit; Flags: recursesubdirs createallsubdirs
Source: setvars.bat; DestDir: {app}

[Registry]
; RubyInstaller identification for admin
; FIXME: Proper registry keys for RailsInstaller (admin)
;Root: HKLM; Subkey: Software\RailsInstaller; ValueType: string; ValueName: ; ValueData: ; Flags: uninsdeletevalue uninsdeletekeyifempty; Check: IsAdmin

; RubyInstaller identification for non-admin
; FIXME: Proper registry key for RailsInstaller (user)
;Root: HKCU; Subkey: Software\RailsInstaller; ValueType: string; ValueName: ; ValueData: ; Flags: uninsdeletevalue uninsdeletekeyifempty; Check: IsNotAdmin

[Icons]
Name: {group}\Interactive Ruby; Filename: {app}\{#RubyPath}\bin\irb.bat; IconFilename: {app}\{#RubyPath}\bin\ruby.exe; Flags: createonlyiffileexists
Name: {group}\RubyGems Documentation Server; Filename: {app}\{#RubyPath}\bin\gem.bat; Parameters: server; IconFilename: {app}\{#RubyPath}\bin\ruby.exe; Flags: createonlyiffileexists runminimized
Name: {group}\Start Command Prompt with RailsInstaller; Filename: {sys}\cmd.exe; Parameters: /E:ON /K {app}\setrbvars.bat; WorkingDir: {%HOMEDRIVE}{%HOMEPATH}; IconFilename: {sys}\cmd.exe; Flags: createonlyiffileexists
Name: {group}\{cm:UninstallProgram,{#InstallerName}}; Filename: {uninstallexe}

[Code]
#include "util.iss"
#include "railsinstaller_gui.iss"

function GetInstallDate(Param: String): String;
begin
  Result := GetDateTimeString('yyyymmdd', #0 , #0);
end;

procedure CurStepChanged(const CurStep: TSetupStep);
begin

  // TODO move into ssPostInstall just after install completes?
  if CurStep = ssInstall then
  begin
    if UsingWinNT then
    begin
      Log(Format('Selected Tasks - Path: %d', [PathChkBox.State]));

      if IsModifyPath then
        ModifyPath([ExpandConstant('{app}') + '\{#RubyPath}\bin']);
        ModifyPath([ExpandConstant('{app}') + '\Git\cmd']);

    end else
      MsgBox('Looks like you''ve got on older, unsupported Windows version.' #13 +
             'Proceeding with a reduced feature set installation.',
             mbInformation, MB_OK);
  end;
end;

procedure RegisterPreviousData(PreviousDataKey: Integer);
begin
  {* store install choices so we can use during uninstall *}
  if IsModifyPath then
    SetPreviousData(PreviousDataKey, 'PathModified', 'yes');

  SetPreviousData(PreviousDataKey, 'RailsInstallerId', '{#InstallerVersion}');
end;

procedure CurUninstallStepChanged(const CurUninstallStep: TUninstallStep);
begin
  if CurUninstallStep = usUninstall then
  begin
    if UsingWinNT then
    begin
      if GetPreviousData('PathModified', 'no') = 'yes' then
        ModifyPath([ExpandConstant('{app}') + '\{#RubyPath}\bin']);
        ModifyPath([ExpandConstant('{app}') + '\Git\cmd']);
    end;
  end;
end;


installer signed

installer signed

#define MyAppName "Zydeo Chinese dictionary"
#define MyInstallerName "Zydeo Chinese dictionary installer"
#define MyAppNameShort "Zydeo"
#define MyAppVersion "1.0"
#define MyAppPublisher "Gbor L Ugray"
#define MyAppURL "http://zydeo.net/"
#define MyAppExeName "Zydeo.exe"

[Setup]
AppId={{46634FB3-D868-44F3-A55C-80852B9FC5AA}
MinVersion=0,5.01.2600
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={pf}\{#MyAppNameShort}
DefaultGroupName={#MyAppName}
DisableProgramGroupPage=yes
Compression=lzma/normal
SolidCompression=yes
ShowLanguageDialog=no
DirExistsWarning=no
OutputDir=..\_install
OutputBaseFilename=ZydeoSetup-v{#MyAppVersion}
ArchitecturesInstallIn64BitMode=x64
FlatComponentsList=False
AlwaysShowComponentsList=False
ShowComponentSizes=False
DisableReadyPage=True
DisableReadyMemo=True
SetupIconFile=ZydeoSetup.ico
UninstallDisplayIcon={app}\ZydeoSetup.ico
WizardImageBackColor=clWhite
WizardImageFile=installer1.bmp
WizardSmallImageFile=installer2.bmp
VersionInfoCompany={#MyAppPublisher}
VersionInfoDescription={#MyAppName} setup
VersionInfoCopyright=(C) {#MyAppPublisher} 2015
VersionInfoVersion={#MyAppVersion}.0.0
SignTool=SignTool

[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"

[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"

[Files]
Source: isxdl.dll; Flags: dontcopy
Source: isxdl_english.ini; Flags: dontcopy

Source: "..\_bin\Zydeo.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\_bin\ZD.AU.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\_bin\ZD.CedictEngine.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\_bin\ZD.Common.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\_bin\ZD.Gui.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\_bin\ZD.Gui.Zen.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\_bin\ZD.HanziLookup.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\_bin\ZD.Texts.dll"; DestDir: "{app}"; Flags: ignoreversion

Source: "..\_bin\Fonts\Ubuntu-Bold.ttf"; DestDir: "{app}\Fonts"; Flags: ignoreversion
Source: "..\_bin\Fonts\Neuton-Regular.ttf"; DestDir: "{app}\Fonts"; Flags: ignoreversion
Source: "..\_bin\Data\cedict-zydeo.bin"; DestDir: "{app}\Data"; Flags: ignoreversion
Source: "..\_bin\Data\strokes-zydeo.bin"; DestDir: "{app}\Data"; Flags: ignoreversion

Source: "..\License.html"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\License-CC-BY-SA-3.0.txt"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\License-GNU-GPL-3.0.txt"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\License-ArphicPublicLicense.txt"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\License-SIL-OpenFont-1.1.txt"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\License-UbuntuFont-1.0.txt"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\License-Apache-2.0.txt"; DestDir: "{app}"; Flags: ignoreversion

Source: "ZydeoSetup.ico"; DestDir: "{app}"; Flags: ignoreversion

[UninstallDelete]
;; Delete fonts that we have downloaded (not installed).
Type: filesandordirs; Name: "{app}\Fonts"

[Icons]
Name: "{commonstartmenu}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{commondesktop}\{#MyAppNameShort}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon

[Run]
Filename: {app}\ZD.AU.exe; Parameters: /install; WorkingDir: {app}; Flags: runascurrentuser
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent

[UninstallRun]
Filename: {app}\ZD.AU.exe; Parameters: /uninstall; WorkingDir: {app}; Flags: runascurrentuser

[Messages]
WinVersionTooLowError=Zydeo requires Windows XP Service Pack 3 or later.

[CustomMessages]
english.DotNetAdmin=Zydeo needs Microsoft .NET Framework v4.0 to be installed by an Administrator
english.Downloading=Downloading dependencies
english.DownloadDetail=Zydeo needs to download and install dependencies. Please wait while Setup is downloading extra files to your computer.

[Code]
var
  dotnetRedistPath: string;
  downloadNeeded: boolean;
  dotNetNeeded: boolean;
  arphicNeeded: boolean;
  notoNeeded: boolean;

procedure isxdl_AddFile(URL, Filename: AnsiString);
external 'isxdl_AddFile@files:isxdl.dll stdcall';
function isxdl_DownloadFiles(hWnd: Integer): Integer;
external 'isxdl_DownloadFiles@files:isxdl.dll stdcall';
function isxdl_SetOption(Option, Value: AnsiString): Integer;
external 'isxdl_SetOption@files:isxdl.dll stdcall';

const
  dotnetRedistURL = 'http://download.microsoft.com/download/1/B/E/1BE39E79-7E39-46A3-96FF-047F95396215/dotNetFx40_Full_setup.exe';
  notoUrl1 = 'http://zydeo.net/downloadinstaller?file=NotoSans-Regular.ttf';
  notoUrl2 = 'http://zydeo.net/downloadinstaller?file=NotoSans-Italic.ttf';
  notoUrl3 = 'http://zydeo.net/downloadinstaller?file=NotoSans-Bold.ttf';
  notoUrl4 = 'http://zydeo.net/downloadinstaller?file=NotoSans-BoldItalic.ttf';
  arphicUrl1 = 'http://zydeo.net/downloadinstaller?file=hdzb_75.ttf';
  arphicUrl2 = 'http://zydeo.net/downloadinstaller?file=ukaitw.ttf';

function InitializeSetup(): Boolean;
var
  Installed_40 : Cardinal;
  Installed_45: Cardinal;
  Version: String;
  QuerySuccess: Boolean;
  dfKaiExists: Boolean;
  kaiTiExists: Boolean;

begin
  Result := true;
  dotNetNeeded := false;
  arphicNeeded := false;
  notoNeeded := false;

  // Check for .NET 4.0 or 4.5 full profile
  RegQueryDWordValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full', 'Install', Installed_40);
  Installed_45 := 0;

  if (Installed_40 <> 0) then
  begin
    QuerySuccess := RegQueryStringValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full', 'Version', Version);
    if not QuerySuccess then  // version unavailable
      Installed_40 := 0;
    if QuerySuccess and (Version[3] = '5') then begin // 4.5
      Installed_40 := 0;
      Installed_45 := 1;
    end;
  end;

  if (not ((Installed_45 <> 0) or (Installed_40 <> 0))) then begin
    dotNetNeeded := true;
    if (not IsAdminLoggedOn()) then begin
      MsgBox(CustomMessage('DotNetAdmin'), mbInformation, MB_OK);
      Result := false;
    end else begin
      dotnetRedistPath := ExpandConstant('{src}\dotNetFx40_Full_x86_x64.exe.exe');
      if not FileExists(dotnetRedistPath) then begin
        dotnetRedistPath := ExpandConstant('{tmp}\dotNetFx40_Full_x86_x64.exe.exe');
        if not FileExists(dotnetRedistPath) then begin
          isxdl_AddFile(dotnetRedistURL, dotnetRedistPath);
          downloadNeeded := true;
        end;
      end;
      SetIniString('install', 'dotnetRedist', dotnetRedistPath, ExpandConstant('{tmp}\dep.ini'));
    end;
  end;

  // Check for existence of Segoe UI. If missing, Noto is needed.
  if (not FileExists(ExpandConstant('{fonts}\segoeui.ttf'))) then begin
    notoNeeded := true;
    downloadNeeded := true;
    isxdl_AddFile(notoUrl1, ExpandConstant('{tmp}\tmp-NotoSans-Regular.ttf'));
    isxdl_AddFile(notoUrl2, ExpandConstant('{tmp}\tmp-NotoSans-Italic.ttf'));
    isxdl_AddFile(notoUrl3, ExpandConstant('{tmp}\tmp-NotoSans-Bold.ttf'));
    isxdl_AddFile(notoUrl4, ExpandConstant('{tmp}\tmp-NotoSans-BoldItalic.ttf'));
  end;

  // Check for existence of both DFKai-SB (kaiu.ttf) and KaiTi (simkai.ttf)
  // If either is missing, must get Arphic fonts
  dfKaiExists := FileExists(ExpandConstant('{fonts}\kaiu.ttf'));
  kaiTiExists := FileExists(ExpandConstant('{fonts}\simkai.ttf'));
  if (not dfKaiExists or not kaiTiExists) then begin
    arphicNeeded := true;
    downloadNeeded := true;
    isxdl_AddFile(arphicUrl1, ExpandConstant('{tmp}\tmp-hdzb_75.ttf'));
    isxdl_AddFile(arphicUrl2, ExpandConstant('{tmp}\tmp-ukaitw.ttf'));
  end;
end;

function NextButtonClick(CurPage: Integer): Boolean;
var
  hWnd: Integer;
  ResultCode: Integer;
  LangFileName: string;

begin
  Result := true;

  if CurPage = wpWelcome then begin
    hWnd := StrToInt(ExpandConstant('{wizardhwnd}'));
    // don't try to init isxdl if it's not needed because it will error on < ie 3
    if downloadNeeded then begin
  	  // Download dialog localized
  	  LangFileName := 'isxdl_' + ExpandConstant('{language}') + '.ini';
      ExtractTemporaryFile(LangFileName);
      isxdl_SetOption('language', ExpandConstant('{tmp}\') + LangFileName);
      isxdl_SetOption('label', CustomMessage('Downloading'));
      isxdl_SetOption('description', CustomMessage('DownloadDetail'));
      // Download files
      if isxdl_DownloadFiles(hWnd) = 0 then Result := false;
    end;
    if (Result = true) and (dotNetNeeded = true) then begin
      if Exec(ExpandConstant(dotnetRedistPath), '', '', SW_SHOW, ewWaitUntilTerminated, ResultCode) then begin
         // handle success if necessary; ResultCode contains the exit code
         if not (ResultCode = 0) then begin
           Result := false;
         end;
      end else begin
         // handle failure if necessary; ResultCode contains the error code
         Result := false;
      end;
    end;
  end;
end;

procedure CurStepChanged(CurStep: TSetupStep);
begin
  if CurStep = ssPostInstall then
  begin
    // Copy downloaded files to app folder: Noto font(s)
    if notoNeeded then begin
      FileCopy(ExpandConstant('{tmp}\tmp-NotoSans-Regular.ttf'), ExpandConstant('{app}\Fonts\NotoSans-Regular.ttf'), False);
      FileCopy(ExpandConstant('{tmp}\tmp-NotoSans-Italic.ttf'), ExpandConstant('{app}\Fonts\NotoSans-Italic.ttf'), False);
      FileCopy(ExpandConstant('{tmp}\tmp-NotoSans-Bold.ttf'), ExpandConstant('{app}\Fonts\NotoSans-Bold.ttf'), False);
      FileCopy(ExpandConstant('{tmp}\tmp-NotoSans-BlodItalic.ttf'), ExpandConstant('{app}\Fonts\NotoSans-BlodItalic.ttf'), False);
    end;
    // Copy downloaded files to app folder: Arphic Kai font(s)
    if arphicNeeded then begin
      FileCopy(ExpandConstant('{tmp}\tmp-hdzb_75.ttf'), ExpandConstant('{app}\Fonts\hdzb_75.ttf'), False);
      FileCopy(ExpandConstant('{tmp}\tmp-ukaitw.ttf'), ExpandConstant('{app}\Fonts\ukaitw.ttf'), False);
    end;
  end;
end;

#define MyAppName "Zydeo Chinese dictionary"
#define MyAppNameShort "Zydeo"
#define MyAppVersion "1.0"
#define MyAppPublisher "Gbor L Ugray"
#define MyAppURL "http://zydeo.net/"
#define MyAppExeName "Zydeo.exe"

[Setup]
AppId={{46634FB3-D868-44F3-A55C-80852B9FC5AA}
MinVersion=0,5.01.2600
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={pf}\{#MyAppNameShort}
DefaultGroupName={#MyAppName}
DisableProgramGroupPage=yes
Compression=lzma/normal
SolidCompression=yes
ShowLanguageDialog=no
DirExistsWarning=no
OutputDir=..\_install
OutputBaseFilename=ZydeoSetup-v{#MyAppVersion}
ArchitecturesInstallIn64BitMode=x64
FlatComponentsList=False
AlwaysShowComponentsList=False
ShowComponentSizes=False
DisableReadyPage=True
DisableReadyMemo=True
SetupIconFile=ZydeoSetup.ico
UninstallDisplayIcon={app}\ZydeoSetup.ico
WizardImageBackColor=clWhite
WizardImageFile=installer1.bmp
WizardSmallImageFile=installer2.bmp
VersionInfoCompany={#MyAppPublisher}
VersionInfoDescription={#MyAppName} setup
VersionInfoCopyright=(C) {#MyAppPublisher} 2015
VersionInfoVersion={#MyAppVersion}.0.0

[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"

[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"

[Files]
Source: isxdl.dll; Flags: dontcopy
Source: isxdl_english.ini; Flags: dontcopy

Source: "..\_bin\Zydeo.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\_bin\ZD.AU.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\_bin\ZD.CedictEngine.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\_bin\ZD.Common.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\_bin\ZD.Gui.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\_bin\ZD.Gui.Zen.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\_bin\ZD.HanziLookup.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\_bin\ZD.Texts.dll"; DestDir: "{app}"; Flags: ignoreversion

Source: "..\_bin\Fonts\Ubuntu-Bold.ttf"; DestDir: "{app}\Fonts"; Flags: ignoreversion
Source: "..\_bin\Fonts\Neuton-Regular.ttf"; DestDir: "{app}\Fonts"; Flags: ignoreversion
Source: "..\_bin\Data\cedict-zydeo.bin"; DestDir: "{app}\Data"; Flags: ignoreversion
Source: "..\_bin\Data\strokes-zydeo.bin"; DestDir: "{app}\Data"; Flags: ignoreversion

Source: "..\License.html"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\License-CC-BY-SA-3.0.txt"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\License-GNU-GPL-3.0.txt"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\License-ArphicPublicLicense.txt"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\License-SIL-OpenFont-1.1.txt"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\License-UbuntuFont-1.0.txt"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\License-Apache-2.0.txt"; DestDir: "{app}"; Flags: ignoreversion

Source: "ZydeoSetup.ico"; DestDir: "{app}"; Flags: ignoreversion

[UninstallDelete]
;; Delete fonts that we have downloaded (not installed).
Type: filesandordirs; Name: "{app}\Fonts"

[Icons]
Name: "{commonstartmenu}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{commondesktop}\{#MyAppNameShort}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon

[Run]
Filename: {app}\ZD.AU.exe; Parameters: /install; WorkingDir: {app}; Flags: runascurrentuser
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent

[UninstallRun]
Filename: {app}\ZD.AU.exe; Parameters: /uninstall; WorkingDir: {app}; Flags: runascurrentuser

[Messages]
WinVersionTooLowError=Zydeo requires Windows XP Service Pack 3 or later.

[CustomMessages]
english.DotNetAdmin=Zydeo needs Microsoft .NET Framework v4.0 to be installed by an Administrator
english.Downloading=Downloading dependencies
english.DownloadDetail=Zydeo needs to download and install dependencies. Please wait while Setup is downloading extra files to your computer.

[Code]
var
  dotnetRedistPath: string;
  downloadNeeded: boolean;
  dotNetNeeded: boolean;
  arphicNeeded: boolean;
  notoNeeded: boolean;

procedure isxdl_AddFile(URL, Filename: AnsiString);
external 'isxdl_AddFile@files:isxdl.dll stdcall';
function isxdl_DownloadFiles(hWnd: Integer): Integer;
external 'isxdl_DownloadFiles@files:isxdl.dll stdcall';
function isxdl_SetOption(Option, Value: AnsiString): Integer;
external 'isxdl_SetOption@files:isxdl.dll stdcall';

const
  dotnetRedistURL = 'http://download.microsoft.com/download/1/B/E/1BE39E79-7E39-46A3-96FF-047F95396215/dotNetFx40_Full_setup.exe';
  notoUrl1 = 'http://zydeo.net/downloadinstaller?file=NotoSans-Regular.ttf';
  notoUrl2 = 'http://zydeo.net/downloadinstaller?file=NotoSans-Italic.ttf';
  notoUrl3 = 'http://zydeo.net/downloadinstaller?file=NotoSans-Bold.ttf';
  notoUrl4 = 'http://zydeo.net/downloadinstaller?file=NotoSans-BoldItalic.ttf';
  arphicUrl1 = 'http://zydeo.net/downloadinstaller?file=hdzb_75.ttf';
  arphicUrl2 = 'http://zydeo.net/downloadinstaller?file=ukaitw.ttf';

function InitializeSetup(): Boolean;
var
  Installed_40 : Cardinal;
  Installed_45: Cardinal;
  Version: String;
  QuerySuccess: Boolean;
  dfKaiExists: Boolean;
  kaiTiExists: Boolean;

begin
  Result := true;
  dotNetNeeded := false;
  arphicNeeded := false;
  notoNeeded := false;

  // Check for .NET 4.0 or 4.5 full profile
  RegQueryDWordValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full', 'Install', Installed_40);
  Installed_45 := 0;

  if (Installed_40 <> 0) then
  begin
    QuerySuccess := RegQueryStringValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full', 'Version', Version);
    if not QuerySuccess then  // version unavailable
      Installed_40 := 0;
    if QuerySuccess and (Version[3] = '5') then begin // 4.5
      Installed_40 := 0;
      Installed_45 := 1;
    end;
  end;

  if (not ((Installed_45 <> 0) or (Installed_40 <> 0))) then begin
    dotNetNeeded := true;
    if (not IsAdminLoggedOn()) then begin
      MsgBox(CustomMessage('DotNetAdmin'), mbInformation, MB_OK);
      Result := false;
    end else begin
      dotnetRedistPath := ExpandConstant('{src}\dotNetFx40_Full_x86_x64.exe.exe');
      if not FileExists(dotnetRedistPath) then begin
        dotnetRedistPath := ExpandConstant('{tmp}\dotNetFx40_Full_x86_x64.exe.exe');
        if not FileExists(dotnetRedistPath) then begin
          isxdl_AddFile(dotnetRedistURL, dotnetRedistPath);
          downloadNeeded := true;
        end;
      end;
      SetIniString('install', 'dotnetRedist', dotnetRedistPath, ExpandConstant('{tmp}\dep.ini'));
    end;
  end;

  // Check for existence of Segoe UI. If missing, Noto is needed.
  if (not FileExists(ExpandConstant('{fonts}\segoeui.ttf'))) then begin
    notoNeeded := true;
    downloadNeeded := true;
    isxdl_AddFile(notoUrl1, ExpandConstant('{tmp}\tmp-NotoSans-Regular.ttf'));
    isxdl_AddFile(notoUrl2, ExpandConstant('{tmp}\tmp-NotoSans-Italic.ttf'));
    isxdl_AddFile(notoUrl3, ExpandConstant('{tmp}\tmp-NotoSans-Bold.ttf'));
    isxdl_AddFile(notoUrl4, ExpandConstant('{tmp}\tmp-NotoSans-BoldItalic.ttf'));
  end;

  // Check for existence of both DFKai-SB (kaiu.ttf) and KaiTi (simkai.ttf)
  // If either is missing, must get Arphic fonts
  dfKaiExists := FileExists(ExpandConstant('{fonts}\kaiu.ttf'));
  kaiTiExists := FileExists(ExpandConstant('{fonts}\simkai.ttf'));
  if (not dfKaiExists or not kaiTiExists) then begin
    arphicNeeded := true;
    downloadNeeded := true;
    isxdl_AddFile(arphicUrl1, ExpandConstant('{tmp}\tmp-hdzb_75.ttf'));
    isxdl_AddFile(arphicUrl2, ExpandConstant('{tmp}\tmp-ukaitw.ttf'));
  end;
end;

function NextButtonClick(CurPage: Integer): Boolean;
var
  hWnd: Integer;
  ResultCode: Integer;
  LangFileName: string;

begin
  Result := true;

  if CurPage = wpWelcome then begin
    hWnd := StrToInt(ExpandConstant('{wizardhwnd}'));
    // don't try to init isxdl if it's not needed because it will error on < ie 3
    if downloadNeeded then begin
  	  // Download dialog localized
  	  LangFileName := 'isxdl_' + ExpandConstant('{language}') + '.ini';
      ExtractTemporaryFile(LangFileName);
      isxdl_SetOption('language', ExpandConstant('{tmp}\') + LangFileName);
      isxdl_SetOption('label', CustomMessage('Downloading'));
      isxdl_SetOption('description', CustomMessage('DownloadDetail'));
      // Download files
      if isxdl_DownloadFiles(hWnd) = 0 then Result := false;
    end;
    if (Result = true) and (dotNetNeeded = true) then begin
      if Exec(ExpandConstant(dotnetRedistPath), '', '', SW_SHOW, ewWaitUntilTerminated, ResultCode) then begin
         // handle success if necessary; ResultCode contains the exit code
         if not (ResultCode = 0) then begin
           Result := false;
         end;
      end else begin
         // handle failure if necessary; ResultCode contains the error code
         Result := false;
      end;
    end;
  end;
end;

procedure CurStepChanged(CurStep: TSetupStep);
begin
  if CurStep = ssPostInstall then
  begin
    // Copy downloaded files to app folder: Noto font(s)
    if notoNeeded then begin
      FileCopy(ExpandConstant('{tmp}\tmp-NotoSans-Regular.ttf'), ExpandConstant('{app}\Fonts\NotoSans-Regular.ttf'), False);
      FileCopy(ExpandConstant('{tmp}\tmp-NotoSans-Italic.ttf'), ExpandConstant('{app}\Fonts\NotoSans-Italic.ttf'), False);
      FileCopy(ExpandConstant('{tmp}\tmp-NotoSans-Bold.ttf'), ExpandConstant('{app}\Fonts\NotoSans-Bold.ttf'), False);
      FileCopy(ExpandConstant('{tmp}\tmp-NotoSans-BlodItalic.ttf'), ExpandConstant('{app}\Fonts\NotoSans-BlodItalic.ttf'), False);
    end;
    // Copy downloaded files to app folder: Arphic Kai font(s)
    if arphicNeeded then begin
      FileCopy(ExpandConstant('{tmp}\tmp-hdzb_75.ttf'), ExpandConstant('{app}\Fonts\hdzb_75.ttf'), False);
      FileCopy(ExpandConstant('{tmp}\tmp-ukaitw.ttf'), ExpandConstant('{app}\Fonts\ukaitw.ttf'), False);
    end;
  end;
end;