Now the user has to accept the license on install

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

#define MyAppName "Gryptonite"
#define MyAppVersion "3.0.4_beta"
#define MyAppPublisher "Rapstallion"
#define MyAppURL "https://github.com/karagog/Gryptonite"
#define MyAppExeName "gryptonite.exe"

#define TopDir "..\.."

[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={{60E0B876-8466-4046-B96F-F40B00515DFD}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={pf}\{#MyAppName}
DefaultGroupName={#MyAppName}
OutputDir=.
OutputBaseFilename={#MyAppName}_{#MyAppVersion}_setup
Compression=lzma
SolidCompression=yes
LicenseFile={#TopDir}\LICENSE

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

[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked; OnlyBelowVersion: 0,6.1
Name: "associate"; Description: "&Associate .gdb and .GPdb files"; GroupDescription: "Files:";

[Files]
; License files
Source: "{#TopDir}\LICENSE"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\NOTICE"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\installers\LICENSE_CRYPTOPP"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\installers\LICENSE_QT"; DestDir: "{app}"; Flags: ignoreversion

; Application executables and shared libraries
Source: "{#TopDir}\bin\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\grypto_transforms.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\grypto_legacy_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\grypto_core.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\grypto_ui.dll"; DestDir: "{app}"; Flags: ignoreversion

; GUtil shared libraries
Source: "{#TopDir}\bin\GUtil.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\GUtilAboutPlugin.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\GUtilCryptoPP.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\GUtilQt.dll"; DestDir: "{app}"; Flags: ignoreversion

; Qt shared libraries
Source: "{#TopDir}\bin\Qt5Core.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\Qt5Gui.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\Qt5Widgets.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\Qt5Sql.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\Qt5Svg.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\Qt5Xml.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\Qt5Network.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\Qt5WinExtras.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\ssleay32.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\libeay32.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\libgcc_s_dw2-1.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\libstdc++-6.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\libwinpthread-1.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\icudt52.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\icuin52.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\icuuc52.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\platforms\qwindows.dll"; DestDir: "{app}/platforms"; Flags: ignoreversion
Source: "{#TopDir}\bin\sqldrivers\qsqlite.dll"; DestDir: "{app}/sqldrivers"; Flags: ignoreversion
Source: "{#TopDir}\bin\accessible\*"; DestDir: "{app}/accessible"; Flags: ignoreversion
Source: "{#TopDir}\bin\imageformats\*"; DestDir: "{app}/imageformats"; Flags: ignoreversion
Source: "{#TopDir}\bin\iconengines\*"; DestDir: "{app}/iconengines"; Flags: ignoreversion
; NOTE: Don't use "Flags: ignoreversion" on any shared system files

[Registry]
; Create a handler for regular database files
Root: HKCR; Subkey: "Gryptonite.gdb"; ValueType: string; ValueData: "Gryptonite Database"; Flags: uninsdeletekey;
Root: HKCR; Subkey: "Gryptonite.gdb\DefaultIcon"; ValueType: string; ValueData: "{app}\{#MyAppExeName}"; Flags: uninsdeletekey;
Root: HKCR; Subkey: "Gryptonite.gdb\shell\Open\Command"; ValueType: string; ValueData: "{app}\{#MyAppExeName} ""%1"" "; Flags: uninsdeletekey;

; These file types are only associated if the "associate" task was selected (the default)
Root: HKCR; Subkey: ".gdb"; ValueType: string; ValueData: "Gryptonite.gdb"; Flags: uninsdeletekey; Tasks: associate
Root: HKCR; Subkey: ".GPdb"; ValueType: string; ValueData: "Gryptonite.gdb"; Flags: uninsdeletekey; Tasks: associate

[Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: quicklaunchicon

[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent

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

#define MyAppName "Gryptonite"
#define MyAppVersion "3.0.4_beta"
#define MyAppPublisher "Rapstallion"
#define MyAppURL "https://github.com/karagog/Gryptonite"
#define MyAppExeName "gryptonite.exe"

#define TopDir "..\.."

[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={{60E0B876-8466-4046-B96F-F40B00515DFD}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={pf}\{#MyAppName}
DefaultGroupName={#MyAppName}
OutputDir=.
OutputBaseFilename={#MyAppName}_{#MyAppVersion}_setup
Compression=lzma
SolidCompression=yes

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

[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked; OnlyBelowVersion: 0,6.1
Name: "associate"; Description: "&Associate .gdb and .GPdb files"; GroupDescription: "Files:";

[Files]
; License files
Source: "{#TopDir}\LICENSE"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\NOTICE"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\installers\LICENSE_CRYPTOPP"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\installers\LICENSE_QT"; DestDir: "{app}"; Flags: ignoreversion

; Application executables and shared libraries
Source: "{#TopDir}\bin\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\grypto_transforms.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\grypto_legacy_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\grypto_core.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\grypto_ui.dll"; DestDir: "{app}"; Flags: ignoreversion

; GUtil shared libraries
Source: "{#TopDir}\bin\GUtil.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\GUtilAboutPlugin.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\GUtilCryptoPP.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\GUtilQt.dll"; DestDir: "{app}"; Flags: ignoreversion

; Qt shared libraries
Source: "{#TopDir}\bin\Qt5Core.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\Qt5Gui.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\Qt5Widgets.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\Qt5Sql.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\Qt5Svg.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\Qt5Xml.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\Qt5Network.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\Qt5WinExtras.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\ssleay32.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\libeay32.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\libgcc_s_dw2-1.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\libstdc++-6.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\libwinpthread-1.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\icudt52.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\icuin52.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\icuuc52.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#TopDir}\bin\platforms\qwindows.dll"; DestDir: "{app}/platforms"; Flags: ignoreversion
Source: "{#TopDir}\bin\sqldrivers\qsqlite.dll"; DestDir: "{app}/sqldrivers"; Flags: ignoreversion
Source: "{#TopDir}\bin\accessible\*"; DestDir: "{app}/accessible"; Flags: ignoreversion
Source: "{#TopDir}\bin\imageformats\*"; DestDir: "{app}/imageformats"; Flags: ignoreversion
Source: "{#TopDir}\bin\iconengines\*"; DestDir: "{app}/iconengines"; Flags: ignoreversion
; NOTE: Don't use "Flags: ignoreversion" on any shared system files

[Registry]
; Create a handler for regular database files
Root: HKCR; Subkey: "Gryptonite.gdb"; ValueType: string; ValueData: "Gryptonite Database"; Flags: uninsdeletekey;
Root: HKCR; Subkey: "Gryptonite.gdb\DefaultIcon"; ValueType: string; ValueData: "{app}\{#MyAppExeName}"; Flags: uninsdeletekey;
Root: HKCR; Subkey: "Gryptonite.gdb\shell\Open\Command"; ValueType: string; ValueData: "{app}\{#MyAppExeName} ""%1"" "; Flags: uninsdeletekey;

; These file types are only associated if the "associate" task was selected (the default)
Root: HKCR; Subkey: ".gdb"; ValueType: string; ValueData: "Gryptonite.gdb"; Flags: uninsdeletekey; Tasks: associate
Root: HKCR; Subkey: ".GPdb"; ValueType: string; ValueData: "Gryptonite.gdb"; Flags: uninsdeletekey; Tasks: associate

[Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: quicklaunchicon

[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent


Updated setup to copy navxmxp libraries and headers to new 2017 WPI Library locations.

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

#define MyAppName "navX-MXP"
#define MyAppVersion "0.0.000"
#define MyAppPublisher "KauaiLabs, Inc."
#define MyAppURL "http://navx-mxp.kauailabs.com"

[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={{B8D8466D-9D83-4F6A-922B-9BE227E48E5B}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={pf}\Kauai Labs\navX-MXP
DisableDirPage=yes
DefaultGroupName=Kauai Labs\navX-MXP
DisableProgramGroupPage=yes
OutputBaseFilename=setup
Compression=lzma
SolidCompression=yes
OutputDir=.\Output_navX-MXP

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

[Icons]
Name: "{group}\navXConfig"; Filename: "{app}\navXConfig\navXConfig.exe"; WorkingDir: "{app}\navXConfig"; IconFilename: "{app}\graphics\configuration.ico"
Name: "{group}\navXMagCalibrator"; Filename: "{app}\navXMagCalibrator\navXMagCalibrator.exe"; WorkingDir: "{app}\navXMagCalibrator"
Name: "{group}\navXFirmwareUpdater"; Filename: "{app}\navXFirmwareUpdater\navXFirmwareUpdater.exe"; WorkingDir: "{app}\navXFirmwareUpdater"; IconFilename: "{app}\graphics\download.ico"
Name: "{group}\navXUI"; Filename: "{app}\navXUI\navXUI"; WorkingDir: "{app}\navXUI"; IconFilename: "{app}\graphics\dashboard.ico"
Name: "{group}\Online Documentation"; Filename: "{app}\navx-mxp-software.url"; IconFilename: "{app}\graphics\information.ico"
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
Name: "{group}\RoboRIO Libaries & Samples"; Filename: "{win}\explorer"; Parameters: "{%HOMEPATH}\navx-mxp"

[Files]
Source: "..\drivers\windows\vcp\*.*"; DestDir: "{app}\installers\vcp"; Flags: recursesubdirs
Source: "..\drivers\windows\dfu\*.*"; DestDir: "{app}\installers\dfu"; Flags: recursesubdirs
Source: "..\c#\navXMagCalibrator\bin\Release\*.*"; DestDir: "{app}\navXMagCalibrator"; Flags: recursesubdirs
Source: "..\c#\navXConfig\bin\Release\*.*"; DestDir: "{app}\navXConfig"; Flags: recursesubdirs
Source: "..\c#\navXFirmwareUpdater\bin\Release\*.*"; DestDir: "{app}\navXFirmwareUpdater"; Flags: recursesubdirs
Source: "..\processing_output\*.*"; DestDir: "{app}\navXUI"; Flags: recursesubdirs
Source: "weblinks\navx-mxp-software.url"; DestDir: "{app}"

Source: "graphics\*.*"; DestDir: "{app}\graphics"; Flags: recursesubdirs
Source: "..\roborio\java\navx_frc\src\com\*.*"; DestDir: "{%HOMEPATH}\navx-mxp\java\src\com"; Flags: recursesubdirs
Source: "..\roborio\java\navx_frc\src\docs\*.*"; DestDir: "{%HOMEPATH}\navx-mxp\java\docs"; Flags: recursesubdirs
Source: "..\roborio\java\navx_frc\jar\navx_frc.jar"; DestDir: "{%HOMEPATH}\navx-mxp\java\lib"
Source: "..\roborio\java\navx_frc\jar\navx_frc.jar"; DestDir: "{%HOMEPATH}\wpilib\user\java\lib"
Source: "..\roborio\java\navXMXP_Java_DataMonitor\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\java\examples\DataMonitor"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\java\navXMXP_Java_FieldCentricDrive\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\java\examples\FieldCentricDrive"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\java\navXMXP_Java_RotateToAngle\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\java\examples\RotateToAngle"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\java\navXMXP_Java_AutoBalance\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\java\examples\AutoBalance"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\java\navXMXP_Java_CollisionDetection\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\java\examples\CollisionDetection"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\java\navXMXP_Java_MotionDetection\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\java\examples\MotionDetection"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\java\navXMXP_ExpansionIO\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\java\examples\ExpansionIO"; Flags: createallsubdirs recursesubdirs

Source: "..\roborio\c++\navx_frc_cpp\Debug\*.a"; DestDir: "{%HOMEPATH}\navx-mxp\cpp\lib"
Source: "..\roborio\c++\navx_frc_cpp\Debug\*.a"; DestDir: "{%HOMEPATH}\wpilib\user\cpp\lib"
Source: "..\roborio\c++\navx_frc_cpp\include\*.*"; DestDir: "{%HOMEPATH}\navx-mxp\cpp\include"
Source: "..\roborio\c++\navx_frc_cpp\include\*.*"; DestDir: "{%HOMEPATH}\wpilib\user\cpp\include"
Source: "..\roborio\c++\navx_frc_cpp\src\*.*"; DestDir: "{%HOMEPATH}\navx-mxp\cpp\src"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\c++\doxygen\html\*.*"; DestDir: "{%HOMEPATH}\navx-mxp\cpp\docs"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\c++\navXMXP_CPP_DataMonitor\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\cpp\examples\DataMonitor"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\c++\navXMXP_CPP_FieldCentricDrive\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\cpp\examples\FieldCentricDrive"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\c++\navXMXP_CPP_RotateToAngle\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\cpp\examples\RotateToAngle"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\c++\navXMXP_CPP_AutoBalance\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\cpp\examples\AutoBalance"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\c++\navXMXP_CPP_CollisionDetection\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\cpp\examples\CollisionDetection"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\c++\navXMXP_CPP_MotionDetection\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\cpp\examples\MotionDetection"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\c++\navXMXP_CPP_ExpansionIO\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\cpp\examples\ExpansionIO"; Flags: createallsubdirs recursesubdirs

Source: "..\roborio\labview\*.*"; DestDir: "{%HOMEPATH}\navx-mxp\labview"; Flags: createallsubdirs recursesubdirs

Source: "..\android\navx_ftc\build\outputs\aar\*.aar"; DestDir: "{%HOMEPATH}\navx-mxp\android\libs"
Source: "..\android\OpModes\*.*"; DestDir: "{%HOMEPATH}\navx-mxp\android\examples"; Flags: createallsubdirs recursesubdirs
Source: "..\android\navx_ftc\docs\*.*"; DestDir: "{%HOMEPATH}\navx-mxp\android\docs"; Flags: recursesubdirs

Source: "..\stm32\bin\navx-mxp*.hex"; DestDir: "{%HOMEPATH}\navx-mxp\firmware"; Flags:

[Run]
Filename: "{app}\installers\vcp\Win7\dpinst_amd64.exe"; Parameters: "/SW"; Flags: 64bit; OnlyBelowVersion: 0,6.2; Check: IsWin64
Filename: "{app}\installers\vcp\Win7\dpinst_x86.exe"; Parameters: "/SW"; Flags: 32bit; OnlyBelowVersion: 0,6.2; Check: not IsWin64
Filename: "{app}\installers\vcp\Win8\dpinst_amd64.exe"; Parameters: "/SW"; Flags: 64bit; MinVersion: 0,6.2; Check: IsWin64
Filename: "{app}\installers\vcp\Win8\dpinst_x86.exe"; Parameters: "/SW"; Flags: 32bit; MinVersion: 0,6.2; Check: not IsWin64
Filename: "{app}\installers\dfu\dpinst_amd64.exe"; Parameters: "/SW"; Flags: 64bit; Check: IsWin64
Filename: "{app}\installers\dfu\dpinst_x86.exe"; Parameters: "/SW"; Flags: 32bit; Check: not IsWin64

[Dirs]
Name: "{app}\navXFirmwareUpdater"; Flags: uninsalwaysuninstall
Name: "{app}\navXConfig"; Flags: uninsalwaysuninstall
Name: "{app}\navXMagCalibrator"; Flags: uninsalwaysuninstall
Name: "{app}\installers"
Name: "{app}\navXUI"; Flags: uninsalwaysuninstall

[Code]
function InitializeSetup(): Boolean;
var
 ErrorCode: Integer;
 JavaInstalled : Boolean;
 ResultMsg : Boolean;
 Versions: TArrayOfString;
 I: Integer;
 regRoot: Integer;
begin
 // Check which view of registry should be taken:
 regRoot := HKLM
 begin
  if IsWin64 then
  begin
   regRoot := HKLM64
  end;
 end;
 if (RegGetSubkeyNames(regRoot, 'SOFTWARE\JavaSoft\Java Runtime Environment', Versions)) or (RegGetSubkeyNames(regRoot, 'SOFTWARE\JavaSoft\Java Development Kit', Versions)) then
 begin
  for I := 0 to GetArrayLength(Versions)-1 do
   if JavaInstalled = true then
   begin
    //do nothing
   end else
   begin
    if ( Versions[I][2]='.' ) and ( ( StrToInt(Versions[I][1]) > 1 ) or ( ( StrToInt(Versions[I][1]) = 1 ) and ( StrToInt(Versions[I][3]) >= 7 ) ) ) then
    begin
     JavaInstalled := true;
    end else
    begin
     JavaInstalled := false;
    end;
   end;
 end else
 begin
  JavaInstalled := false;
 end;

 if JavaInstalled then
 begin
  Result := true;
 end else
    begin
  ResultMsg := MsgBox('Oracle Java v1.7 or newer not found in the system. Java 1.7 or later is required to run this application (can be installed after this installation too). Do you want to continue?',
   mbConfirmation, MB_YESNO) = idYes;
  if ResultMsg = false then
  begin
   Result := false;
  end else
  begin
   Result := true;
   ShellExec('open',
    'http://www.java.com/getjava/',
    '','',SW_SHOWNORMAL,ewNoWait,ErrorCode);
  end;
    end;
end;

end.

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

#define MyAppName "navX-MXP"
#define MyAppVersion "0.0.000"
#define MyAppPublisher "KauaiLabs, Inc."
#define MyAppURL "http://navx-mxp.kauailabs.com"

[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={{B8D8466D-9D83-4F6A-922B-9BE227E48E5B}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={pf}\Kauai Labs\navX-MXP
DisableDirPage=yes
DefaultGroupName=Kauai Labs\navX-MXP
DisableProgramGroupPage=yes
OutputBaseFilename=setup
Compression=lzma
SolidCompression=yes
OutputDir=.\Output_navX-MXP

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

[Icons]
Name: "{group}\navXConfig"; Filename: "{app}\navXConfig\navXConfig.exe"; WorkingDir: "{app}\navXConfig"; IconFilename: "{app}\graphics\configuration.ico"
Name: "{group}\navXMagCalibrator"; Filename: "{app}\navXMagCalibrator\navXMagCalibrator.exe"; WorkingDir: "{app}\navXMagCalibrator"
Name: "{group}\navXFirmwareUpdater"; Filename: "{app}\navXFirmwareUpdater\navXFirmwareUpdater.exe"; WorkingDir: "{app}\navXFirmwareUpdater"; IconFilename: "{app}\graphics\download.ico"
Name: "{group}\navXUI"; Filename: "{app}\navXUI\navXUI"; WorkingDir: "{app}\navXUI"; IconFilename: "{app}\graphics\dashboard.ico"
Name: "{group}\Online Documentation"; Filename: "{app}\navx-mxp-software.url"; IconFilename: "{app}\graphics\information.ico"
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
Name: "{group}\RoboRIO Libaries & Samples"; Filename: "{win}\explorer"; Parameters: "{%HOMEPATH}\navx-mxp"

[Files]
Source: "..\drivers\windows\vcp\*.*"; DestDir: "{app}\installers\vcp"; Flags: recursesubdirs
Source: "..\drivers\windows\dfu\*.*"; DestDir: "{app}\installers\dfu"; Flags: recursesubdirs
Source: "..\c#\navXMagCalibrator\bin\Release\*.*"; DestDir: "{app}\navXMagCalibrator"; Flags: recursesubdirs
Source: "..\c#\navXConfig\bin\Release\*.*"; DestDir: "{app}\navXConfig"; Flags: recursesubdirs
Source: "..\c#\navXFirmwareUpdater\bin\Release\*.*"; DestDir: "{app}\navXFirmwareUpdater"; Flags: recursesubdirs
Source: "..\processing_output\*.*"; DestDir: "{app}\navXUI"; Flags: recursesubdirs
Source: "weblinks\navx-mxp-software.url"; DestDir: "{app}"

Source: "graphics\*.*"; DestDir: "{app}\graphics"; Flags: recursesubdirs
Source: "..\roborio\java\navx_frc\src\com\*.*"; DestDir: "{%HOMEPATH}\navx-mxp\java\src\com"; Flags: recursesubdirs
Source: "..\roborio\java\navx_frc\src\docs\*.*"; DestDir: "{%HOMEPATH}\navx-mxp\java\docs"; Flags: recursesubdirs
Source: "..\roborio\java\navx_frc\jar\navx_frc.jar"; DestDir: "{%HOMEPATH}\navx-mxp\java\lib"
Source: "..\roborio\java\navXMXP_Java_DataMonitor\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\java\examples\DataMonitor"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\java\navXMXP_Java_FieldCentricDrive\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\java\examples\FieldCentricDrive"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\java\navXMXP_Java_RotateToAngle\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\java\examples\RotateToAngle"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\java\navXMXP_Java_AutoBalance\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\java\examples\AutoBalance"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\java\navXMXP_Java_CollisionDetection\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\java\examples\CollisionDetection"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\java\navXMXP_Java_MotionDetection\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\java\examples\MotionDetection"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\java\navXMXP_ExpansionIO\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\java\examples\ExpansionIO"; Flags: createallsubdirs recursesubdirs

Source: "..\roborio\c++\navx_frc_cpp\Debug\*.a"; DestDir: "{%HOMEPATH}\navx-mxp\cpp\lib"
Source: "..\roborio\c++\navx_frc_cpp\include\*.*"; DestDir: "{%HOMEPATH}\navx-mxp\cpp\include"
Source: "..\roborio\c++\navx_frc_cpp\src\*.*"; DestDir: "{%HOMEPATH}\navx-mxp\cpp\src"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\c++\doxygen\html\*.*"; DestDir: "{%HOMEPATH}\navx-mxp\cpp\docs"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\c++\navXMXP_CPP_DataMonitor\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\cpp\examples\DataMonitor"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\c++\navXMXP_CPP_FieldCentricDrive\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\cpp\examples\FieldCentricDrive"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\c++\navXMXP_CPP_RotateToAngle\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\cpp\examples\RotateToAngle"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\c++\navXMXP_CPP_AutoBalance\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\cpp\examples\AutoBalance"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\c++\navXMXP_CPP_CollisionDetection\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\cpp\examples\CollisionDetection"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\c++\navXMXP_CPP_MotionDetection\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\cpp\examples\MotionDetection"; Flags: createallsubdirs recursesubdirs
Source: "..\roborio\c++\navXMXP_CPP_ExpansionIO\*.*"; Excludes: "build,dist,bin"; DestDir: "{%HOMEPATH}\navx-mxp\cpp\examples\ExpansionIO"; Flags: createallsubdirs recursesubdirs

Source: "..\roborio\labview\*.*"; DestDir: "{%HOMEPATH}\navx-mxp\labview"; Flags: createallsubdirs recursesubdirs

Source: "..\android\navx_ftc\build\outputs\aar\*.aar"; DestDir: "{%HOMEPATH}\navx-mxp\android\libs"
Source: "..\android\OpModes\*.*"; DestDir: "{%HOMEPATH}\navx-mxp\android\examples"; Flags: createallsubdirs recursesubdirs
Source: "..\android\navx_ftc\docs\*.*"; DestDir: "{%HOMEPATH}\navx-mxp\android\docs"; Flags: recursesubdirs

Source: "..\stm32\bin\navx-mxp*.hex"; DestDir: "{%HOMEPATH}\navx-mxp\firmware"; Flags:

[Run]
Filename: "{app}\installers\vcp\Win7\dpinst_amd64.exe"; Parameters: "/SW"; Flags: 64bit; OnlyBelowVersion: 0,6.2; Check: IsWin64
Filename: "{app}\installers\vcp\Win7\dpinst_x86.exe"; Parameters: "/SW"; Flags: 32bit; OnlyBelowVersion: 0,6.2; Check: not IsWin64
Filename: "{app}\installers\vcp\Win8\dpinst_amd64.exe"; Parameters: "/SW"; Flags: 64bit; MinVersion: 0,6.2; Check: IsWin64
Filename: "{app}\installers\vcp\Win8\dpinst_x86.exe"; Parameters: "/SW"; Flags: 32bit; MinVersion: 0,6.2; Check: not IsWin64
Filename: "{app}\installers\dfu\dpinst_amd64.exe"; Parameters: "/SW"; Flags: 64bit; Check: IsWin64
Filename: "{app}\installers\dfu\dpinst_x86.exe"; Parameters: "/SW"; Flags: 32bit; Check: not IsWin64

[Dirs]
Name: "{app}\navXFirmwareUpdater"; Flags: uninsalwaysuninstall
Name: "{app}\navXConfig"; Flags: uninsalwaysuninstall
Name: "{app}\navXMagCalibrator"; Flags: uninsalwaysuninstall
Name: "{app}\installers"
Name: "{app}\navXUI"; Flags: uninsalwaysuninstall

[Code]
function InitializeSetup(): Boolean;
var
 ErrorCode: Integer;
 JavaInstalled : Boolean;
 ResultMsg : Boolean;
 Versions: TArrayOfString;
 I: Integer;
 regRoot: Integer;
begin
 // Check which view of registry should be taken:
 regRoot := HKLM
 begin
  if IsWin64 then
  begin
   regRoot := HKLM64
  end;
 end;
 if (RegGetSubkeyNames(regRoot, 'SOFTWARE\JavaSoft\Java Runtime Environment', Versions)) or (RegGetSubkeyNames(regRoot, 'SOFTWARE\JavaSoft\Java Development Kit', Versions)) then
 begin
  for I := 0 to GetArrayLength(Versions)-1 do
   if JavaInstalled = true then
   begin
    //do nothing
   end else
   begin
    if ( Versions[I][2]='.' ) and ( ( StrToInt(Versions[I][1]) > 1 ) or ( ( StrToInt(Versions[I][1]) = 1 ) and ( StrToInt(Versions[I][3]) >= 7 ) ) ) then
    begin
     JavaInstalled := true;
    end else
    begin
     JavaInstalled := false;
    end;
   end;
 end else
 begin
  JavaInstalled := false;
 end;

 if JavaInstalled then
 begin
  Result := true;
 end else
    begin
  ResultMsg := MsgBox('Oracle Java v1.7 or newer not found in the system. Java 1.7 or later is required to run this application (can be installed after this installation too). Do you want to continue?',
   mbConfirmation, MB_YESNO) = idYes;
  if ResultMsg = false then
  begin
   Result := false;
  end else
  begin
   Result := true;
   ShellExec('open',
    'http://www.java.com/getjava/',
    '','',SW_SHOWNORMAL,ewNoWait,ErrorCode);
  end;
    end;
end;

end.


disable Polish in installer because translation is still in progress.

#define SourceDir "..\"
#define AppName "AIMP Control Plugin"
#define SrcApp "temp_build\Release\Control Plugin.dll"
; use absolute path as GetFileVersion() argument since there is problem with relative path when we execute this script from command line.
#define FileVerStr GetFileVersion(SourcePath + "\" + SourceDir + SrcApp)
#define StripBuild(VerStr) Copy(VerStr, 1, RPos(".", VerStr)-1)
#define AppVerStr StripBuild(FileVerStr)
#define PluginWorkDirectoryName "Control Plugin"
#define AimpPluginsDirectoryName "Plugins"
#define FreeImage_VERSION GetEnv('FreeImage_VERSION')
#define LegacyPluginExecutableFilename "aimp_control_plugin.dll"
#define LogsDirectoryName "logs"
#define AlbumCoverCacheDirectoryName "album_covers_cache"
#define LegacyAIMP3_6_RC_PluginDirName "aimp_control_plugin"

[Setup]

SourceDir={#SourceDir}
AppName={#AppName}
AppVersion={#AppVerStr}
AppVerName={#AppName} {#AppVerStr}
UninstallDisplayName={#AppName} {#AppVerStr}
UninstallFilesDir={app}\{#PluginWorkDirectoryName}
VersionInfoVersion={#FileVerStr}
VersionInfoTextVersion={#AppVerStr}
VersionInfoDescription=AIMP player plugin. Provides network access to AIMP player.
VersionInfoProductName={#AppName}
VersionInfoProductVersion={#FileVerStr}
OutputBaseFilename=aimp_control_plugin-{#FileVerStr}-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={{F171581D-00CD-4E77-8982-B1B68FDCAAFA}
AppPublisher=Alexey Ivanov
AppCopyright=Copyright © 2015 Alexey Ivanov
AppPublisherURL=https://github.com/a0ivanov/aimp-control-plugin
AppSupportURL=http://code.google.com/p/aimp-control-plugin/w/list
AppUpdatesURL=https://github.com/a0ivanov/aimp-control-plugin/releases/latest

DefaultDirName={#AimpPluginsDirectoryName}
DefaultGroupName={#AppName}
DisableProgramGroupPage=true
OutputDir=temp_build\Release\distrib\
SetupIconFile=inno_setup_data\icons\aimp_control_plugin_installer.ico
Compression=lzma/ultra
SolidCompression=true
InternalCompressLevel=ultra
PrivilegesRequired=admin
DirExistsWarning=no
AllowUNCPath=false
AppendDefaultDirName=true

[Languages]
; Language name is used on Donation page as {language} constant.
Name: en; MessagesFile: inno_setup_data\English.isl; LicenseFile: License-English.txt;
Name: ru; MessagesFile: inno_setup_data\Russian.isl; LicenseFile: License-Russian.txt;
Name: cs; MessagesFile: inno_setup_data\Czech.isl;   LicenseFile: License-English.txt;

[Files]
Source: "{#SrcApp}"; DestDir: "{code:GetPluginDllDestinationDir}"; DestName: "{#PluginWorkDirectoryName}.dll"; BeforeInstall: RemoveLegacyPluginExecutable; Flags: ignoreversion
Source: "temp_build\Release\htdocs\*"; DestDir: "{code:GetBrowserScriptsDir}"; Flags: ignoreversion recursesubdirs createallsubdirs
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
Source: "inno_setup_data\default_settings.dat"; DestDir: "{code:GetPluginSettingsDir}"; DestName: "settings.dat"; Flags: onlyifdoesntexist; AfterInstall: AfterInstallSettingsFile( ExpandConstant('{code:GetPluginSettingsDir}\settings.dat') )
Source: "3rd_party\FreeImage\{#FreeImage_VERSION}\Dist\FreeImage.dll"; DestDir: "{code:GetFreeImageDLLsDstDir}"; Flags: ignoreversion
Source: "3rd_party\FreeImage\{#FreeImage_VERSION}\Wrapper\FreeImagePlus\dist\FreeImagePlus.dll"; DestDir: "{code:GetFreeImageDLLsDstDir}"; Flags: ignoreversion
Source: "temp_build\Release\SettingsManager\*"; DestDir: "{code:GetSettingsManagerDir}"; Flags: ignoreversion recursesubdirs createallsubdirs

[Registry]
; etc.

[UninstallDelete]
Type: filesandordirs; Name: "{code:GetBrowserScriptsDirOnUninstall}\{#AlbumCoverCacheDirectoryName}"
Type: filesandordirs; Name: "{code:GetPluginSettingsDir}\{#LogsDirectoryName}"

[Code]
var
  BrowserScriptsDirPage: TInputDirWizardPage;
  AimpVersionSelectionPage: TInputOptionWizardPage;
  PluginOptionsPage: TInputOptionWizardPage;
  SettingsManagerInstallationPage: TOutputMsgMemoWizardPage;
  AfterInstallPage: TOutputMsgMemoWizardPage;
  AllowNetworkAccess: Boolean;
  AllowFilesUpload: Boolean;
  AllowFilesDeletion: Boolean;
  EnableScheduler: Boolean;
  SettingsFileDestination: String;
  Port: Integer;

procedure InitDonationPage; forward;
function GetTextForSettingsManagerInstallationMemo(): AnsiString; forward;

procedure InitializeWizard;
begin
  { Set AIMP player version, used to determine default path of Aimp's Plugins directory. }
  AimpVersionSelectionPage := CreateInputOptionPage(wpLicense,
                                                    ExpandConstant('{cm:AimpVerionSelectionMsg1}'),
                                                    ExpandConstant('{cm:AimpVerionSelectionMsg2}'),
                                                    ExpandConstant('{cm:AimpVerionSelectionMsg3}'),
                                                    True,
                                                    False
                                                    );
  AimpVersionSelectionPage.Add('AIMP2');
  AimpVersionSelectionPage.Add('AIMP3');
  AimpVersionSelectionPage.Add('AIMP4');

  AimpVersionSelectionPage.SelectedValueIndex := 2; { default is AIMP4 }

  BrowserScriptsDirPage := CreateInputDirPage(wpSelectDir,
                                              ExpandConstant('{cm:BrowserScriptsDirSelectionMsg1}'),
                                              ExpandConstant('{cm:BrowserScriptsDirSelectionMsg2}'),
                                              ExpandConstant('{cm:BrowserScriptsDirSelectionMsg3}'),
                                              False,
                                              ''
                                              );
  BrowserScriptsDirPage.Add('');

  InitDonationPage();

  PluginOptionsPage := CreateInputOptionPage(BrowserScriptsDirPage.ID,
                                            ExpandConstant('{cm:PluginOptionsTitle}'),
                                            ExpandConstant('{cm:PluginOptionsDescription}'),
                                            ExpandConstant('{cm:PluginOptionsSubDescription}'),
                                            False, False);

  PluginOptionsPage.Add(ExpandConstant('{cm:OptionNetworkCheckBox}'));
  PluginOptionsPage.Add(ExpandConstant('{cm:OptionUploadTracksCheckBox}'));
  PluginOptionsPage.Add(ExpandConstant('{cm:OptionPhysicalTrackDeletionCheckBox}'));
  PluginOptionsPage.Add(ExpandConstant('{cm:OptionSchedulerCheckBox}'));

  SettingsManagerInstallationPage := CreateOutputMsgMemoPage(PluginOptionsPage.ID,
                                          ExpandConstant('{cm:SettingsManagerInstallationTitle}'),
                                          ExpandConstant('{cm:SettingsManagerInstallationDescription}'),
                                          ExpandConstant('{cm:SettingsManagerInstallationSubDescription}'),
                                          GetTextForSettingsManagerInstallationMemo());

  AfterInstallPage := CreateOutputMsgMemoPage(wpInfoAfter,
   SetupMessage(msgWizardInfoAfter),
   SetupMessage(msgInfoAfterLabel),
   SetupMessage(msgInfoAfterClickLabel),
   '' // memo text will be set later by AfterInstallPage.RichEditViewer.RTFText.
  );

  Port := 3333;
end;

procedure TerminateAimpExecutionIfNeedeed(); forward;
function GetInfoAfterMemoText() : String; forward;
function DefaultWritableBrowserScriptsDir(): String; forward;

procedure CurPageChanged(CurPageID: Integer);
begin
  if CurPageID = wpSelectDir then
    begin
    WizardForm.DirEdit.Text := ExpandConstant('{pf}\{code:GetAimpPlayerAppDirName}\{code:AimpPluginsDirName}')

    TerminateAimpExecutionIfNeedeed(); { must do this after WizardForm.DirEdit.Text set. }
    end
  else if CurPageID = BrowserScriptsDirPage.ID then
    begin
    SettingsFileDestination := ExpandConstant('{code:GetPluginSettingsDir}\settings.dat');

    { Set default values, using settings that were stored last time if possible }
    BrowserScriptsDirPage.Values[0] := DefaultWritableBrowserScriptsDir();
    end
  else if CurPageID = wpReady then
     begin
     AllowNetworkAccess := PluginOptionsPage.Values[0];
     AllowFilesUpload := PluginOptionsPage.Values[1];
     AllowFilesDeletion := PluginOptionsPage.Values[2];
     EnableScheduler := PluginOptionsPage.Values[3];
     AfterInstallPage.RichEditViewer.RTFText := GetInfoAfterMemoText();
     end
end;

function IsDotNetDetected(version: string; service: cardinal): boolean; forward;

function ShouldSkipPage(PageID: Integer): Boolean;
begin
  // initialize result to not skip any page (not necessary, but safer)
  Result := False;

  // if the page that is asked to be skipped is your custom page, then...
  if PageID = SettingsManagerInstallationPage.ID then
    Result := IsDotNetDetected('v4\Full', 0)
end;

function GetTextForSettingsManagerInstallationMemo(): AnsiString;
begin
   Result := ExpandConstant('{cm:SettingsManagerInstallationMessage}');
end;

function DefaultWritableBrowserScriptsDir(): String;
begin
  //GetPreviousData( 'BrowserScriptsDir',
  //                  ExpandConstant('{code:GetPluginWorkDir}\htdocs')
  //                );

  Result := ExpandConstant('{userappdata}\{code:GetAimpPlayerAppDataDirName}\{#PluginWorkDirectoryName}\htdocs');
end;

function IsAimp2(): Boolean; forward;
function IsAimp3(): Boolean; forward;

function GetAimpPlayerAppDataDirName(): String;
begin
  { Return the name of AppData directory for selected AIMP player version }
  if IsAimp3() then
	  Result := 'AIMP3'
  else
	  Result := 'AIMP';
end;

function GetBrowserScriptsDir(Param: String): String;
begin
  { Return the selected BrowserScriptsDir }
  Result := BrowserScriptsDirPage.Values[0];
end;

function IsAimp2(): Boolean;
begin
   Result := AimpVersionSelectionPage.SelectedValueIndex = 0;
end;

function IsAimp3(): Boolean;
begin
   Result := AimpVersionSelectionPage.SelectedValueIndex = 1;
end;

function GetPluginWorkDir(Param: String): String;
begin
  Result := ExpandConstant('{app}\{#PluginWorkDirectoryName}')
end;

function GetPluginSettingsDir(Param: String): String;
begin
  Result := ExpandConstant('{app}\{#PluginWorkDirectoryName}')
end;

function GetFreeImageDLLsDstDir(Param: String): String;
begin
  Result := ExpandConstant('{app}\{#PluginWorkDirectoryName}')
end;

function GetSettingsManagerDir(Param: String): String;
begin
  Result := ExpandConstant('{app}\{#PluginWorkDirectoryName}\SettingsManager')
end;

function AimpPluginsDirName(Param: String): String;
begin
  { Return name of AIMP's Plugins directory. }
  Result := ExpandConstant('{#AimpPluginsDirectoryName}')
  { We do not distinguish between AIMP2/3 Plugins directory names
    since supporting of this difference is hard
    while Windows is case insensitive.
  if IsAimp2() then
    Result := 'PlugIns'
  else
    Result := 'Plugins';
  }
end;

function GetAimpIniFileName(): String; forward;

function GetAimp3VersionCode(): Integer;
var
    version: Longint;
    aimpIniFilePath: String;
begin
   aimpIniFilePath := ExpandConstant('{app}\..\' + GetAimpIniFileName());
   version := GetIniInt('System', 'Version', 0, 0, 555555, aimpIniFilePath);
   Log('Aimp version is: ' + IntToStr(version));

   Result := version;
end;

function GetPluginDllDestinationDir(Param: String): String;
var aimpVersionCode: Integer;
begin
    aimpVersionCode := GetAimp3VersionCode();
    if aimpVersionCode >= 3600 then
        Result := ExpandConstant('{app}\{#PluginWorkDirectoryName}')
    else
        Result := ExpandConstant('{app}');
end;

function GetAimpPlayerAppDirName(Param: String): String;
begin
  { Return the name of program directory for selected AIMP player version }
  if IsAimp2() then
    Result := 'AIMP2'
  else if IsAimp3() then
    Result := 'AIMP3'
  else
    Result := 'AIMP'; // AIMP4+.
end;

function GetAimpIniFileName(): String;
begin
  { Return the name of ini file in program directory for selected AIMP player version }
  if IsAimp3() then
    Result := 'AIMP3.ini'
  else
    Result := 'AIMP.ini'; // AIMP4+, AIMP2 has no ini file in program directory.
end;

procedure RemoveLegacyPluginExecutable();
var path: String;
begin
  path := ExpandConstant('{app}\{#PluginWorkDirectoryName}\{#LegacyPluginExecutableFilename}');
  DeleteFile(path);
  path := ExpandConstant('{app}\{#LegacyPluginExecutableFilename}');
  DeleteFile(path);
  path := ExpandConstant('{app}\{#LegacyAIMP3_6_RC_PluginDirName}');
  DelTree(path, True, True, True);
end;

procedure RegisterPreviousData(PreviousDataKey: Integer);
begin
  SetPreviousData(PreviousDataKey, 'BrowserScriptsDir', BrowserScriptsDirPage.Values[0]);
end;

function BooleanToString(condition: Boolean): String;
begin
  if (condition) then
    Result := 'true'
  else
    Result := 'false';
end;

procedure AfterInstallSettingsFile(Path: String);
var
  // See http://msdn.microsoft.com/en-us/library/ms757878(VS.85).aspx for details about
  XMLDoc : Variant;       // IXMLDOMDocument
  DocRootNodes : Variant; // IXMLDOMNodeList
  DocRootNode : Variant;  // IXMLDOMNode
  HttpServerNode : Variant;  // IXMLDOMNode
  AllInterfacesNode : Variant;  // IXMLDOMNode
  MiscNode : Variant;  // IXMLDOMNode
  Nodes : Variant;        // IXMLDOMNode
  Node : Variant;        // IXMLDOMNode
begin
  //MsgBox('Try to load the XML file: ' + Path, mbInformation, mb_Ok);

  { Load the XML File }
  XMLDoc := CreateOleObject('Msxml2.DOMDocument');
  XMLDoc.async := False;
  XMLDoc.resolveExternals := False;
  XMLDoc.setProperty('SelectionLanguage', 'XPath');
  XMLDoc.load(Path);
  if XMLDoc.parseError.errorCode <> 0 then
    RaiseException('Error in xml file "' + Path + '" on line ' + IntToStr(XMLDoc.parseError.line) + ', position ' + IntToStr(XMLDoc.parseError.linepos) + ': ' + XMLDoc.parseError.reason);

  //MsgBox('Loaded the XML file.', mbInformation, mb_Ok);

  { Modify the XML document }
  DocRootNodes := XMLDoc.selectNodes('//httpserver/document_root');
  //MsgBox('Mathing nodes: ' + IntToStr(DocRootNodes.length), mbInformation, mb_Ok);
  DocRootNode := DocRootNodes.item(0);
  DocRootNode.Text := GetBrowserScriptsDir('');

  Nodes := XMLDoc.selectNodes('//httpserver/port');
  if (Nodes.length > 0) then
    Port := Nodes.item(0).Text;

  HttpServerNode := XMLDoc.selectNodes('//httpserver').item(0);
  if (AllowNetworkAccess) then
    begin
    Nodes := XMLDoc.selectNodes('//httpserver/ip_to_bind');
    if (Nodes.length > 0) then
       HttpServerNode.removeChild(Nodes.item(0));

    Nodes := XMLDoc.selectNodes('//httpserver/port');
    if (Nodes.length > 0) then
       HttpServerNode.removeChild(Nodes.item(0));

    Nodes := XMLDoc.selectNodes('//httpserver/all_interfaces');
    if (Nodes.length > 0) then
      begin
      AllInterfacesNode := Nodes.item(0);
      Port := AllInterfacesNode.getAttribute('port');
      end
    else
      begin
      AllInterfacesNode := XMLDoc.createElement('all_interfaces')
      AllInterfacesNode.setAttribute('port', IntToStr(Port));
      HttpServerNode.appendChild(AllInterfacesNode);
      end;
    end;

  MiscNode := XMLDoc.selectNodes('//misc').item(0);

  Nodes := XMLDoc.selectNodes('//misc/enable_track_upload');
  if (Nodes.length > 0) then
    Node := Nodes.item(0)
  else
    begin
    Node := XMLDoc.createElement('enable_track_upload');
    MiscNode.appendChild(Node);
    Node := XMLDoc.selectNodes('//misc/enable_track_upload').item(0);
    end;
  Node.Text := BooleanToString(AllowFilesDeletion);

  Nodes := XMLDoc.selectNodes('//misc/enable_physical_track_deletion');
  if (Nodes.length > 0) then
    Node := Nodes.item(0)
  else
    begin
    Node := XMLDoc.createElement('enable_physical_track_deletion');
    MiscNode.appendChild(Node);
    Node := XMLDoc.selectNodes('//misc/enable_physical_track_deletion').item(0);
    end;
  Node.Text := BooleanToString(AllowFilesDeletion);

  Nodes := XMLDoc.selectNodes('//misc/enable_scheduler');
  if (Nodes.length > 0) then
    Node := Nodes.item(0)
  else
    begin
    Node := XMLDoc.createElement('enable_scheduler');
    MiscNode.appendChild(Node);
    Node := XMLDoc.selectNodes('//misc/enable_scheduler').item(0);
    end;
  Node.Text := BooleanToString(EnableScheduler);

  { Save the XML document }
  XMLDoc.Save(Path);
  //MsgBox('Saved the modified XML as ''' + Path + '''.', mbInformation, mb_Ok);
end;

function UpdateReadyMemo(Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo,
  MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo: String): String;
var
  S: String;
begin
  { Fill the 'Ready Memo' with the normal settings and the custom settings }
  S := '';
  S := S + MemoDirInfo + NewLine;
  S := S + ExpandConstant('{cm:BrowserScriptsDirDestination}') + NewLine + Space + GetBrowserScriptsDir('') + NewLine;
  S := S + ExpandConstant('{cm:SettingsFileDestination}') + NewLine + Space + SettingsFileDestination + NewLine;
  S := S + ExpandConstant('{cm:SettingsManager}') + ':' + NewLine + Space + GetSettingsManagerDir('') + '\SettingsManager.exe' + NewLine;
  Result := S;
end;

function GetAimpHWND(): HWND;
begin
  Result := FindWindowByClassName('AIMP2_RemoteInfo');
end;

function IsAimpLaunched(): boolean;
begin
  Result := GetAimpHWND() <> 0;
end;

const
  WM_AIMP_COMMAND = 1024 + $75;
  WM_AIMP_CALLFUNC = 3;
  AIMP_QUIT = 10;
procedure KillAimp();
begin
  SendMessage(GetAimpHWND(), WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, AIMP_QUIT);
end;

procedure TerminateAimpExecutionIfNeedeed();
begin
  if IsAimpLaunched() then
    if MsgBox(ExpandConstant('{cm:AimpApplicationTerminateQuery}'),
          mbConfirmation,
          MB_YESNO) = IDYES then
      KillAimp();
end;

function GetUninstallString(): String;
var
  sUnInstPath: String;
  sUnInstallString: String;
begin
  sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("AppId")}_is1');
  sUnInstallString := '';
  if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then
    RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString);
  Result := sUnInstallString;
end;

function GetBrowserScriptsStringDirectlyFromRegistry(): String;
var
  sUnInstPath: String;
  sBrowserScriptsString: String;
begin
  sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("AppId")}_is1');
  sBrowserScriptsString := '';
  if not RegQueryStringValue(HKLM, sUnInstPath, 'Inno Setup CodeFile: BrowserScriptsDir', sBrowserScriptsString) then
    RegQueryStringValue(HKCU, sUnInstPath, 'Inno Setup CodeFile: BrowserScriptsDir', sBrowserScriptsString);

  Result := sBrowserScriptsString;
end;

function GetBrowserScriptsString(): String;
begin
  Result := GetPreviousData('BrowserScriptsDir', '');
end;

function IsUpgrade(): Boolean;
begin
  Result := (GetUninstallString() <> '');
end;

function UnInstallOldVersion(): Integer;
var
  sUnInstallString: String;
  iResultCode: Integer;
begin
// Return Values:
// 1 - uninstall string is empty
// 2 - error executing the UnInstallString
// 3 - successfully executed the UnInstallString

  // default return value
  Result := 0;

  // get the uninstall string of the old app
  sUnInstallString := GetUninstallString();
  if sUnInstallString <> '' then begin
    sUnInstallString := RemoveQuotes(sUnInstallString);
    if Exec(sUnInstallString, '/SILENT /NORESTART /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then
      Result := 3
    else
      Result := 2;
  end else
    Result := 1;
end;

function RemoveInstalledBrowserScripts(): Integer;
var
  sBrowserScriptsDir: String;
begin
// Return Values:
// 1 - Browser scripts dir string is empty
// 2 - error executing the DelTree
// 3 - successfully executed the DelTree

  // default return value
  Result := 0;

  // get the uninstall string of the old app.
  sBrowserScriptsDir := GetBrowserScriptsString();
  if sBrowserScriptsDir <> '' then begin
    sBrowserScriptsDir := RemoveQuotes(sBrowserScriptsDir);
    if DelTree(sBrowserScriptsDir, True, True, True) then
      Result := 3
    else
      Result := 2;
  end else
    Result := 1;
end;

function GetBrowserScriptsDirOnUninstall(Param: String): String;
begin
    Result := GetBrowserScriptsString();
end;

procedure CurStepChanged(CurStep: TSetupStep);
begin
  if (CurStep=ssInstall) then
  begin
    if (IsUpgrade()) then
    begin
      // Do not uninstall previous version till it will be possible remain settings file.
      // Instead remove old browser scripts.
      // UnInstallOldVersion();
      RemoveInstalledBrowserScripts();
    end;
  end;
end;

procedure DonationButtonOnClick(Sender: TObject);
var
  ErrorCode: Integer;
  URL: String;
  lang: String;
begin
  lang := ExpandConstant('{language}');
  if (lang <> 'ru') and (lang <> 'en') then lang := 'en';

  URL := 'http://www.a0ivanov.ru/aimp/donate_' + lang + '.html';

  if not ShellExec('', URL, '', '', SW_SHOW, ewNoWait, ErrorCode) then
  begin
    // handle failure if necessary
  end;
end;

procedure InitDonationPage;
var
  Page: TWizardPage;
  Button: TNewButton;
  Label1: TLabel;
begin
  Page := CreateCustomPage(wpInfoAfter, ExpandConstant('{cm:DonatePageTitle}'), ExpandConstant('{cm:DonateMsg}')); // cm:DonatePageTitle2

  Label1 := TLabel.Create(Page);
  Label1.AutoSize := False;
  Label1.Top := ScaleY(15);
  Label1.Left := ScaleX(0);
  Label1.Width := Page.SurfaceWidth;
  Label1.Alignment := taCenter;
  Label1.Caption := ExpandConstant('{cm:DonateMsg}');
  Label1.WordWrap := True;
  Label1.Parent := Page.Surface;

  Button := TNewButton.Create(Page);
  Button.Width := ScaleX(80);
  Button.Height := ScaleY(26);
  Button.Caption := ExpandConstant('{cm:DonateButton}');
  Button.OnClick := @DonationButtonOnClick;
  Button.Parent := Page.Surface;
  Button.Top := Label1.Top + Label1.Height + ScaleY(8);
  Button.Left := Label1.Left + (Label1.Width - Button.Width) / 2;
end;

procedure GetIpAddresses(Addresses : TStringList); forward;
function GetInfoAfterMemoText(): String;
var
  SL : TStringList;
  I: Integer;
  Msg: String;
begin
  if (AllowNetworkAccess) then
     begin
     Msg := ExpandConstant('{cm:InfoAfterPageMemoTextRemoteBegin}');
     SL := TStringList.Create;
     GetIpAddresses(SL);
     For I := 0 to SL.Count - 1 do
       begin
        Msg := Msg + #13#10 + FmtMessage('http://%1:%2/index.htm', [SL.Strings[I], IntToStr(Port)]);
       end;
     SL.Free;
     Msg := Msg + #13#10 + ExpandConstant('{cm:InfoAfterPageMemoTextRemoteEnd}');
     end
   else
     Msg := ExpandConstant('{cm:InfoAfterPageMemoTextLocal}');

   Msg := Msg + #13#10 + #13#10 + ExpandConstant('{cm:SettingsManagerInfo}');
   Result := Msg;
end;

const
 ERROR_INSUFFICIENT_BUFFER = 122;

function GetIpAddrTable( pIpAddrTable: Array of Byte;
  var pdwSize: Cardinal; bOrder: WordBool ): DWORD;
external 'GetIpAddrTable@IpHlpApi.dll stdcall';

procedure GetIpAddresses(Addresses : TStringList);
var
 Size : Cardinal;
 Buffer : Array of Byte;
 IpAddr : String;
 AddrCount : Integer;
 I, J : Integer;
begin
  // Find Size
  if GetIpAddrTable(Buffer,Size,False) = ERROR_INSUFFICIENT_BUFFER then
  begin
     // Allocate Buffer with large enough size
     SetLength(Buffer,Size);
     // Get List of IP Addresses into Buffer
     if GetIpAddrTable(Buffer,Size,True) = 0 then
     begin
       // Find out how many addresses will be returned.
       AddrCount := (Buffer[1] * 256) + Buffer[0];
       // Loop through addresses.
       For I := 0 to AddrCount -1 do
       begin
         IpAddr := '';
         // Loop through each byte of the address
         For J := 0 to 3 do
         begin
           if J > 0 then
             IpAddr := IpAddr + '.';
           // Navigagte through record structure to find correct byte of Addr
           IpAddr := IpAddr + IntToStr(Buffer[I*24+J+4]);
         end;
         Addresses.Add(IpAddr);
       end;
     end;
  end;
end;

function IsDotNetDetected(version: string; service: cardinal): boolean;
// Indicates whether the specified version and service pack of the .NET Framework is installed.
//
// version -- Specify one of these strings for the required .NET Framework version:
//    'v1.1.4322'     .NET Framework 1.1
//    'v2.0.50727'    .NET Framework 2.0
//    'v3.0'          .NET Framework 3.0
//    'v3.5'          .NET Framework 3.5
//    'v4\Client'     .NET Framework 4.0 Client Profile
//    'v4\Full'       .NET Framework 4.0 Full Installation
//    'v4.5'          .NET Framework 4.5
//
// service -- Specify any non-negative integer for the required service pack level:
//    0               No service packs required
//    1, 2, etc.      Service pack 1, 2, etc. required
var
    key: string;
    install, release, serviceCount: cardinal;
    check45, success: boolean;
begin
    // .NET 4.5 installs as update to .NET 4.0 Full
    if version = 'v4.5' then begin
        version := 'v4\Full';
        check45 := true;
    end else
        check45 := false;

    // installation key group for all .NET versions
    key := 'SOFTWARE\Microsoft\NET Framework Setup\NDP\' + version;

    // .NET 3.0 uses value InstallSuccess in subkey Setup
    if Pos('v3.0', version) = 1 then begin
        success := RegQueryDWordValue(HKLM, key + '\Setup', 'InstallSuccess', install);
    end else begin
        success := RegQueryDWordValue(HKLM, key, 'Install', install);
    end;

    // .NET 4.0/4.5 uses value Servicing instead of SP
    if Pos('v4', version) = 1 then begin
        success := success and RegQueryDWordValue(HKLM, key, 'Servicing', serviceCount);
    end else begin
        success := success and RegQueryDWordValue(HKLM, key, 'SP', serviceCount);
    end;

    // .NET 4.5 uses additional value Release
    if check45 then begin
        success := success and RegQueryDWordValue(HKLM, key, 'Release', release);
        success := success and (release >= 378389);
    end;

    result := success and (install = 1) and (serviceCount >= service);
end;

#define SourceDir "..\"
#define AppName "AIMP Control Plugin"
#define SrcApp "temp_build\Release\Control Plugin.dll"
; use absolute path as GetFileVersion() argument since there is problem with relative path when we execute this script from command line.
#define FileVerStr GetFileVersion(SourcePath + "\" + SourceDir + SrcApp)
#define StripBuild(VerStr) Copy(VerStr, 1, RPos(".", VerStr)-1)
#define AppVerStr StripBuild(FileVerStr)
#define PluginWorkDirectoryName "Control Plugin"
#define AimpPluginsDirectoryName "Plugins"
#define FreeImage_VERSION GetEnv('FreeImage_VERSION')
#define LegacyPluginExecutableFilename "aimp_control_plugin.dll"
#define LogsDirectoryName "logs"
#define AlbumCoverCacheDirectoryName "album_covers_cache"
#define LegacyAIMP3_6_RC_PluginDirName "aimp_control_plugin"

[Setup]

SourceDir={#SourceDir}
AppName={#AppName}
AppVersion={#AppVerStr}
AppVerName={#AppName} {#AppVerStr}
UninstallDisplayName={#AppName} {#AppVerStr}
UninstallFilesDir={app}\{#PluginWorkDirectoryName}
VersionInfoVersion={#FileVerStr}
VersionInfoTextVersion={#AppVerStr}
VersionInfoDescription=AIMP player plugin. Provides network access to AIMP player.
VersionInfoProductName={#AppName}
VersionInfoProductVersion={#FileVerStr}
OutputBaseFilename=aimp_control_plugin-{#FileVerStr}-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={{F171581D-00CD-4E77-8982-B1B68FDCAAFA}
AppPublisher=Alexey Ivanov
AppCopyright=Copyright © 2015 Alexey Ivanov
AppPublisherURL=https://github.com/a0ivanov/aimp-control-plugin
AppSupportURL=http://code.google.com/p/aimp-control-plugin/w/list
AppUpdatesURL=https://github.com/a0ivanov/aimp-control-plugin/releases/latest

DefaultDirName={#AimpPluginsDirectoryName}
DefaultGroupName={#AppName}
DisableProgramGroupPage=true
OutputDir=temp_build\Release\distrib\
SetupIconFile=inno_setup_data\icons\aimp_control_plugin_installer.ico
Compression=lzma/ultra
SolidCompression=true
InternalCompressLevel=ultra
PrivilegesRequired=admin
DirExistsWarning=no
AllowUNCPath=false
AppendDefaultDirName=true

[Languages]
; Language name is used on Donation page as {language} constant.
Name: en; MessagesFile: inno_setup_data\English.isl; LicenseFile: License-English.txt;
Name: ru; MessagesFile: inno_setup_data\Russian.isl; LicenseFile: License-Russian.txt;
Name: cs; MessagesFile: inno_setup_data\Czech.isl;   LicenseFile: License-English.txt;
Name: pl; MessagesFile: inno_setup_data\Polish.isl;  LicenseFile: License-English.txt;

[Files]
Source: "{#SrcApp}"; DestDir: "{code:GetPluginDllDestinationDir}"; DestName: "{#PluginWorkDirectoryName}.dll"; BeforeInstall: RemoveLegacyPluginExecutable; Flags: ignoreversion
Source: "temp_build\Release\htdocs\*"; DestDir: "{code:GetBrowserScriptsDir}"; Flags: ignoreversion recursesubdirs createallsubdirs
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
Source: "inno_setup_data\default_settings.dat"; DestDir: "{code:GetPluginSettingsDir}"; DestName: "settings.dat"; Flags: onlyifdoesntexist; AfterInstall: AfterInstallSettingsFile( ExpandConstant('{code:GetPluginSettingsDir}\settings.dat') )
Source: "3rd_party\FreeImage\{#FreeImage_VERSION}\Dist\FreeImage.dll"; DestDir: "{code:GetFreeImageDLLsDstDir}"; Flags: ignoreversion
Source: "3rd_party\FreeImage\{#FreeImage_VERSION}\Wrapper\FreeImagePlus\dist\FreeImagePlus.dll"; DestDir: "{code:GetFreeImageDLLsDstDir}"; Flags: ignoreversion
Source: "temp_build\Release\SettingsManager\*"; DestDir: "{code:GetSettingsManagerDir}"; Flags: ignoreversion recursesubdirs createallsubdirs

[Registry]
; etc.

[UninstallDelete]
Type: filesandordirs; Name: "{code:GetBrowserScriptsDirOnUninstall}\{#AlbumCoverCacheDirectoryName}"
Type: filesandordirs; Name: "{code:GetPluginSettingsDir}\{#LogsDirectoryName}"

[Code]
var
  BrowserScriptsDirPage: TInputDirWizardPage;
  AimpVersionSelectionPage: TInputOptionWizardPage;
  PluginOptionsPage: TInputOptionWizardPage;
  SettingsManagerInstallationPage: TOutputMsgMemoWizardPage;
  AfterInstallPage: TOutputMsgMemoWizardPage;
  AllowNetworkAccess: Boolean;
  AllowFilesUpload: Boolean;
  AllowFilesDeletion: Boolean;
  EnableScheduler: Boolean;
  SettingsFileDestination: String;
  Port: Integer;

procedure InitDonationPage; forward;
function GetTextForSettingsManagerInstallationMemo(): AnsiString; forward;

procedure InitializeWizard;
begin
  { Set AIMP player version, used to determine default path of Aimp's Plugins directory. }
  AimpVersionSelectionPage := CreateInputOptionPage(wpLicense,
                                                    ExpandConstant('{cm:AimpVerionSelectionMsg1}'),
                                                    ExpandConstant('{cm:AimpVerionSelectionMsg2}'),
                                                    ExpandConstant('{cm:AimpVerionSelectionMsg3}'),
                                                    True,
                                                    False
                                                    );
  AimpVersionSelectionPage.Add('AIMP2');
  AimpVersionSelectionPage.Add('AIMP3');
  AimpVersionSelectionPage.Add('AIMP4');

  AimpVersionSelectionPage.SelectedValueIndex := 2; { default is AIMP4 }

  BrowserScriptsDirPage := CreateInputDirPage(wpSelectDir,
                                              ExpandConstant('{cm:BrowserScriptsDirSelectionMsg1}'),
                                              ExpandConstant('{cm:BrowserScriptsDirSelectionMsg2}'),
                                              ExpandConstant('{cm:BrowserScriptsDirSelectionMsg3}'),
                                              False,
                                              ''
                                              );
  BrowserScriptsDirPage.Add('');

  InitDonationPage();

  PluginOptionsPage := CreateInputOptionPage(BrowserScriptsDirPage.ID,
                                            ExpandConstant('{cm:PluginOptionsTitle}'),
                                            ExpandConstant('{cm:PluginOptionsDescription}'),
                                            ExpandConstant('{cm:PluginOptionsSubDescription}'),
                                            False, False);

  PluginOptionsPage.Add(ExpandConstant('{cm:OptionNetworkCheckBox}'));
  PluginOptionsPage.Add(ExpandConstant('{cm:OptionUploadTracksCheckBox}'));
  PluginOptionsPage.Add(ExpandConstant('{cm:OptionPhysicalTrackDeletionCheckBox}'));
  PluginOptionsPage.Add(ExpandConstant('{cm:OptionSchedulerCheckBox}'));

  SettingsManagerInstallationPage := CreateOutputMsgMemoPage(PluginOptionsPage.ID,
                                          ExpandConstant('{cm:SettingsManagerInstallationTitle}'),
                                          ExpandConstant('{cm:SettingsManagerInstallationDescription}'),
                                          ExpandConstant('{cm:SettingsManagerInstallationSubDescription}'),
                                          GetTextForSettingsManagerInstallationMemo());

  AfterInstallPage := CreateOutputMsgMemoPage(wpInfoAfter,
   SetupMessage(msgWizardInfoAfter),
   SetupMessage(msgInfoAfterLabel),
   SetupMessage(msgInfoAfterClickLabel),
   '' // memo text will be set later by AfterInstallPage.RichEditViewer.RTFText.
  );

  Port := 3333;
end;

procedure TerminateAimpExecutionIfNeedeed(); forward;
function GetInfoAfterMemoText() : String; forward;
function DefaultWritableBrowserScriptsDir(): String; forward;

procedure CurPageChanged(CurPageID: Integer);
begin
  if CurPageID = wpSelectDir then
    begin
    WizardForm.DirEdit.Text := ExpandConstant('{pf}\{code:GetAimpPlayerAppDirName}\{code:AimpPluginsDirName}')

    TerminateAimpExecutionIfNeedeed(); { must do this after WizardForm.DirEdit.Text set. }
    end
  else if CurPageID = BrowserScriptsDirPage.ID then
    begin
    SettingsFileDestination := ExpandConstant('{code:GetPluginSettingsDir}\settings.dat');

    { Set default values, using settings that were stored last time if possible }
    BrowserScriptsDirPage.Values[0] := DefaultWritableBrowserScriptsDir();
    end
  else if CurPageID = wpReady then
     begin
     AllowNetworkAccess := PluginOptionsPage.Values[0];
     AllowFilesUpload := PluginOptionsPage.Values[1];
     AllowFilesDeletion := PluginOptionsPage.Values[2];
     EnableScheduler := PluginOptionsPage.Values[3];
     AfterInstallPage.RichEditViewer.RTFText := GetInfoAfterMemoText();
     end
end;

function IsDotNetDetected(version: string; service: cardinal): boolean; forward;

function ShouldSkipPage(PageID: Integer): Boolean;
begin
  // initialize result to not skip any page (not necessary, but safer)
  Result := False;

  // if the page that is asked to be skipped is your custom page, then...
  if PageID = SettingsManagerInstallationPage.ID then
    Result := IsDotNetDetected('v4\Full', 0)
end;

function GetTextForSettingsManagerInstallationMemo(): AnsiString;
begin
   Result := ExpandConstant('{cm:SettingsManagerInstallationMessage}');
end;

function DefaultWritableBrowserScriptsDir(): String;
begin
  //GetPreviousData( 'BrowserScriptsDir',
  //                  ExpandConstant('{code:GetPluginWorkDir}\htdocs')
  //                );

  Result := ExpandConstant('{userappdata}\{code:GetAimpPlayerAppDataDirName}\{#PluginWorkDirectoryName}\htdocs');
end;

function IsAimp2(): Boolean; forward;
function IsAimp3(): Boolean; forward;

function GetAimpPlayerAppDataDirName(): String;
begin
  { Return the name of AppData directory for selected AIMP player version }
  if IsAimp3() then
	  Result := 'AIMP3'
  else
	  Result := 'AIMP';
end;

function GetBrowserScriptsDir(Param: String): String;
begin
  { Return the selected BrowserScriptsDir }
  Result := BrowserScriptsDirPage.Values[0];
end;

function IsAimp2(): Boolean;
begin
   Result := AimpVersionSelectionPage.SelectedValueIndex = 0;
end;

function IsAimp3(): Boolean;
begin
   Result := AimpVersionSelectionPage.SelectedValueIndex = 1;
end;

function GetPluginWorkDir(Param: String): String;
begin
  Result := ExpandConstant('{app}\{#PluginWorkDirectoryName}')
end;

function GetPluginSettingsDir(Param: String): String;
begin
  Result := ExpandConstant('{app}\{#PluginWorkDirectoryName}')
end;

function GetFreeImageDLLsDstDir(Param: String): String;
begin
  Result := ExpandConstant('{app}\{#PluginWorkDirectoryName}')
end;

function GetSettingsManagerDir(Param: String): String;
begin
  Result := ExpandConstant('{app}\{#PluginWorkDirectoryName}\SettingsManager')
end;

function AimpPluginsDirName(Param: String): String;
begin
  { Return name of AIMP's Plugins directory. }
  Result := ExpandConstant('{#AimpPluginsDirectoryName}')
  { We do not distinguish between AIMP2/3 Plugins directory names
    since supporting of this difference is hard
    while Windows is case insensitive.
  if IsAimp2() then
    Result := 'PlugIns'
  else
    Result := 'Plugins';
  }
end;

function GetAimpIniFileName(): String; forward;

function GetAimp3VersionCode(): Integer;
var
    version: Longint;
    aimpIniFilePath: String;
begin
   aimpIniFilePath := ExpandConstant('{app}\..\' + GetAimpIniFileName());
   version := GetIniInt('System', 'Version', 0, 0, 555555, aimpIniFilePath);
   Log('Aimp version is: ' + IntToStr(version));

   Result := version;
end;

function GetPluginDllDestinationDir(Param: String): String;
var aimpVersionCode: Integer;
begin
    aimpVersionCode := GetAimp3VersionCode();
    if aimpVersionCode >= 3600 then
        Result := ExpandConstant('{app}\{#PluginWorkDirectoryName}')
    else
        Result := ExpandConstant('{app}');
end;

function GetAimpPlayerAppDirName(Param: String): String;
begin
  { Return the name of program directory for selected AIMP player version }
  if IsAimp2() then
    Result := 'AIMP2'
  else if IsAimp3() then
    Result := 'AIMP3'
  else
    Result := 'AIMP'; // AIMP4+.
end;

function GetAimpIniFileName(): String;
begin
  { Return the name of ini file in program directory for selected AIMP player version }
  if IsAimp3() then
    Result := 'AIMP3.ini'
  else
    Result := 'AIMP.ini'; // AIMP4+, AIMP2 has no ini file in program directory.
end;

procedure RemoveLegacyPluginExecutable();
var path: String;
begin
  path := ExpandConstant('{app}\{#PluginWorkDirectoryName}\{#LegacyPluginExecutableFilename}');
  DeleteFile(path);
  path := ExpandConstant('{app}\{#LegacyPluginExecutableFilename}');
  DeleteFile(path);
  path := ExpandConstant('{app}\{#LegacyAIMP3_6_RC_PluginDirName}');
  DelTree(path, True, True, True);
end;

procedure RegisterPreviousData(PreviousDataKey: Integer);
begin
  SetPreviousData(PreviousDataKey, 'BrowserScriptsDir', BrowserScriptsDirPage.Values[0]);
end;

function BooleanToString(condition: Boolean): String;
begin
  if (condition) then
    Result := 'true'
  else
    Result := 'false';
end;

procedure AfterInstallSettingsFile(Path: String);
var
  // See http://msdn.microsoft.com/en-us/library/ms757878(VS.85).aspx for details about
  XMLDoc : Variant;       // IXMLDOMDocument
  DocRootNodes : Variant; // IXMLDOMNodeList
  DocRootNode : Variant;  // IXMLDOMNode
  HttpServerNode : Variant;  // IXMLDOMNode
  AllInterfacesNode : Variant;  // IXMLDOMNode
  MiscNode : Variant;  // IXMLDOMNode
  Nodes : Variant;        // IXMLDOMNode
  Node : Variant;        // IXMLDOMNode
begin
  //MsgBox('Try to load the XML file: ' + Path, mbInformation, mb_Ok);

  { Load the XML File }
  XMLDoc := CreateOleObject('Msxml2.DOMDocument');
  XMLDoc.async := False;
  XMLDoc.resolveExternals := False;
  XMLDoc.setProperty('SelectionLanguage', 'XPath');
  XMLDoc.load(Path);
  if XMLDoc.parseError.errorCode <> 0 then
    RaiseException('Error in xml file "' + Path + '" on line ' + IntToStr(XMLDoc.parseError.line) + ', position ' + IntToStr(XMLDoc.parseError.linepos) + ': ' + XMLDoc.parseError.reason);

  //MsgBox('Loaded the XML file.', mbInformation, mb_Ok);

  { Modify the XML document }
  DocRootNodes := XMLDoc.selectNodes('//httpserver/document_root');
  //MsgBox('Mathing nodes: ' + IntToStr(DocRootNodes.length), mbInformation, mb_Ok);
  DocRootNode := DocRootNodes.item(0);
  DocRootNode.Text := GetBrowserScriptsDir('');

  Nodes := XMLDoc.selectNodes('//httpserver/port');
  if (Nodes.length > 0) then
    Port := Nodes.item(0).Text;

  HttpServerNode := XMLDoc.selectNodes('//httpserver').item(0);
  if (AllowNetworkAccess) then
    begin
    Nodes := XMLDoc.selectNodes('//httpserver/ip_to_bind');
    if (Nodes.length > 0) then
       HttpServerNode.removeChild(Nodes.item(0));

    Nodes := XMLDoc.selectNodes('//httpserver/port');
    if (Nodes.length > 0) then
       HttpServerNode.removeChild(Nodes.item(0));

    Nodes := XMLDoc.selectNodes('//httpserver/all_interfaces');
    if (Nodes.length > 0) then
      begin
      AllInterfacesNode := Nodes.item(0);
      Port := AllInterfacesNode.getAttribute('port');
      end
    else
      begin
      AllInterfacesNode := XMLDoc.createElement('all_interfaces')
      AllInterfacesNode.setAttribute('port', IntToStr(Port));
      HttpServerNode.appendChild(AllInterfacesNode);
      end;
    end;

  MiscNode := XMLDoc.selectNodes('//misc').item(0);

  Nodes := XMLDoc.selectNodes('//misc/enable_track_upload');
  if (Nodes.length > 0) then
    Node := Nodes.item(0)
  else
    begin
    Node := XMLDoc.createElement('enable_track_upload');
    MiscNode.appendChild(Node);
    Node := XMLDoc.selectNodes('//misc/enable_track_upload').item(0);
    end;
  Node.Text := BooleanToString(AllowFilesDeletion);

  Nodes := XMLDoc.selectNodes('//misc/enable_physical_track_deletion');
  if (Nodes.length > 0) then
    Node := Nodes.item(0)
  else
    begin
    Node := XMLDoc.createElement('enable_physical_track_deletion');
    MiscNode.appendChild(Node);
    Node := XMLDoc.selectNodes('//misc/enable_physical_track_deletion').item(0);
    end;
  Node.Text := BooleanToString(AllowFilesDeletion);

  Nodes := XMLDoc.selectNodes('//misc/enable_scheduler');
  if (Nodes.length > 0) then
    Node := Nodes.item(0)
  else
    begin
    Node := XMLDoc.createElement('enable_scheduler');
    MiscNode.appendChild(Node);
    Node := XMLDoc.selectNodes('//misc/enable_scheduler').item(0);
    end;
  Node.Text := BooleanToString(EnableScheduler);

  { Save the XML document }
  XMLDoc.Save(Path);
  //MsgBox('Saved the modified XML as ''' + Path + '''.', mbInformation, mb_Ok);
end;

function UpdateReadyMemo(Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo,
  MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo: String): String;
var
  S: String;
begin
  { Fill the 'Ready Memo' with the normal settings and the custom settings }
  S := '';
  S := S + MemoDirInfo + NewLine;
  S := S + ExpandConstant('{cm:BrowserScriptsDirDestination}') + NewLine + Space + GetBrowserScriptsDir('') + NewLine;
  S := S + ExpandConstant('{cm:SettingsFileDestination}') + NewLine + Space + SettingsFileDestination + NewLine;
  S := S + ExpandConstant('{cm:SettingsManager}') + ':' + NewLine + Space + GetSettingsManagerDir('') + '\SettingsManager.exe' + NewLine;
  Result := S;
end;

function GetAimpHWND(): HWND;
begin
  Result := FindWindowByClassName('AIMP2_RemoteInfo');
end;

function IsAimpLaunched(): boolean;
begin
  Result := GetAimpHWND() <> 0;
end;

const
  WM_AIMP_COMMAND = 1024 + $75;
  WM_AIMP_CALLFUNC = 3;
  AIMP_QUIT = 10;
procedure KillAimp();
begin
  SendMessage(GetAimpHWND(), WM_AIMP_COMMAND, WM_AIMP_CALLFUNC, AIMP_QUIT);
end;

procedure TerminateAimpExecutionIfNeedeed();
begin
  if IsAimpLaunched() then
    if MsgBox(ExpandConstant('{cm:AimpApplicationTerminateQuery}'),
          mbConfirmation,
          MB_YESNO) = IDYES then
      KillAimp();
end;

function GetUninstallString(): String;
var
  sUnInstPath: String;
  sUnInstallString: String;
begin
  sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("AppId")}_is1');
  sUnInstallString := '';
  if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then
    RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString);
  Result := sUnInstallString;
end;

function GetBrowserScriptsStringDirectlyFromRegistry(): String;
var
  sUnInstPath: String;
  sBrowserScriptsString: String;
begin
  sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("AppId")}_is1');
  sBrowserScriptsString := '';
  if not RegQueryStringValue(HKLM, sUnInstPath, 'Inno Setup CodeFile: BrowserScriptsDir', sBrowserScriptsString) then
    RegQueryStringValue(HKCU, sUnInstPath, 'Inno Setup CodeFile: BrowserScriptsDir', sBrowserScriptsString);

  Result := sBrowserScriptsString;
end;

function GetBrowserScriptsString(): String;
begin
  Result := GetPreviousData('BrowserScriptsDir', '');
end;

function IsUpgrade(): Boolean;
begin
  Result := (GetUninstallString() <> '');
end;

function UnInstallOldVersion(): Integer;
var
  sUnInstallString: String;
  iResultCode: Integer;
begin
// Return Values:
// 1 - uninstall string is empty
// 2 - error executing the UnInstallString
// 3 - successfully executed the UnInstallString

  // default return value
  Result := 0;

  // get the uninstall string of the old app
  sUnInstallString := GetUninstallString();
  if sUnInstallString <> '' then begin
    sUnInstallString := RemoveQuotes(sUnInstallString);
    if Exec(sUnInstallString, '/SILENT /NORESTART /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then
      Result := 3
    else
      Result := 2;
  end else
    Result := 1;
end;

function RemoveInstalledBrowserScripts(): Integer;
var
  sBrowserScriptsDir: String;
begin
// Return Values:
// 1 - Browser scripts dir string is empty
// 2 - error executing the DelTree
// 3 - successfully executed the DelTree

  // default return value
  Result := 0;

  // get the uninstall string of the old app.
  sBrowserScriptsDir := GetBrowserScriptsString();
  if sBrowserScriptsDir <> '' then begin
    sBrowserScriptsDir := RemoveQuotes(sBrowserScriptsDir);
    if DelTree(sBrowserScriptsDir, True, True, True) then
      Result := 3
    else
      Result := 2;
  end else
    Result := 1;
end;

function GetBrowserScriptsDirOnUninstall(Param: String): String;
begin
    Result := GetBrowserScriptsString();
end;

procedure CurStepChanged(CurStep: TSetupStep);
begin
  if (CurStep=ssInstall) then
  begin
    if (IsUpgrade()) then
    begin
      // Do not uninstall previous version till it will be possible remain settings file.
      // Instead remove old browser scripts.
      // UnInstallOldVersion();
      RemoveInstalledBrowserScripts();
    end;
  end;
end;

procedure DonationButtonOnClick(Sender: TObject);
var
  ErrorCode: Integer;
  URL: String;
  lang: String;
begin
  lang := ExpandConstant('{language}');
  if (lang <> 'ru') and (lang <> 'en') then lang := 'en';

  URL := 'http://www.a0ivanov.ru/aimp/donate_' + lang + '.html';

  if not ShellExec('', URL, '', '', SW_SHOW, ewNoWait, ErrorCode) then
  begin
    // handle failure if necessary
  end;
end;

procedure InitDonationPage;
var
  Page: TWizardPage;
  Button: TNewButton;
  Label1: TLabel;
begin
  Page := CreateCustomPage(wpInfoAfter, ExpandConstant('{cm:DonatePageTitle}'), ExpandConstant('{cm:DonateMsg}')); // cm:DonatePageTitle2

  Label1 := TLabel.Create(Page);
  Label1.AutoSize := False;
  Label1.Top := ScaleY(15);
  Label1.Left := ScaleX(0);
  Label1.Width := Page.SurfaceWidth;
  Label1.Alignment := taCenter;
  Label1.Caption := ExpandConstant('{cm:DonateMsg}');
  Label1.WordWrap := True;
  Label1.Parent := Page.Surface;

  Button := TNewButton.Create(Page);
  Button.Width := ScaleX(80);
  Button.Height := ScaleY(26);
  Button.Caption := ExpandConstant('{cm:DonateButton}');
  Button.OnClick := @DonationButtonOnClick;
  Button.Parent := Page.Surface;
  Button.Top := Label1.Top + Label1.Height + ScaleY(8);
  Button.Left := Label1.Left + (Label1.Width - Button.Width) / 2;
end;

procedure GetIpAddresses(Addresses : TStringList); forward;
function GetInfoAfterMemoText(): String;
var
  SL : TStringList;
  I: Integer;
  Msg: String;
begin
  if (AllowNetworkAccess) then
     begin
     Msg := ExpandConstant('{cm:InfoAfterPageMemoTextRemoteBegin}');
     SL := TStringList.Create;
     GetIpAddresses(SL);
     For I := 0 to SL.Count - 1 do
       begin
        Msg := Msg + #13#10 + FmtMessage('http://%1:%2/index.htm', [SL.Strings[I], IntToStr(Port)]);
       end;
     SL.Free;
     Msg := Msg + #13#10 + ExpandConstant('{cm:InfoAfterPageMemoTextRemoteEnd}');
     end
   else
     Msg := ExpandConstant('{cm:InfoAfterPageMemoTextLocal}');

   Msg := Msg + #13#10 + #13#10 + ExpandConstant('{cm:SettingsManagerInfo}');
   Result := Msg;
end;

const
 ERROR_INSUFFICIENT_BUFFER = 122;

function GetIpAddrTable( pIpAddrTable: Array of Byte;
  var pdwSize: Cardinal; bOrder: WordBool ): DWORD;
external 'GetIpAddrTable@IpHlpApi.dll stdcall';

procedure GetIpAddresses(Addresses : TStringList);
var
 Size : Cardinal;
 Buffer : Array of Byte;
 IpAddr : String;
 AddrCount : Integer;
 I, J : Integer;
begin
  // Find Size
  if GetIpAddrTable(Buffer,Size,False) = ERROR_INSUFFICIENT_BUFFER then
  begin
     // Allocate Buffer with large enough size
     SetLength(Buffer,Size);
     // Get List of IP Addresses into Buffer
     if GetIpAddrTable(Buffer,Size,True) = 0 then
     begin
       // Find out how many addresses will be returned.
       AddrCount := (Buffer[1] * 256) + Buffer[0];
       // Loop through addresses.
       For I := 0 to AddrCount -1 do
       begin
         IpAddr := '';
         // Loop through each byte of the address
         For J := 0 to 3 do
         begin
           if J > 0 then
             IpAddr := IpAddr + '.';
           // Navigagte through record structure to find correct byte of Addr
           IpAddr := IpAddr + IntToStr(Buffer[I*24+J+4]);
         end;
         Addresses.Add(IpAddr);
       end;
     end;
  end;
end;

function IsDotNetDetected(version: string; service: cardinal): boolean;
// Indicates whether the specified version and service pack of the .NET Framework is installed.
//
// version -- Specify one of these strings for the required .NET Framework version:
//    'v1.1.4322'     .NET Framework 1.1
//    'v2.0.50727'    .NET Framework 2.0
//    'v3.0'          .NET Framework 3.0
//    'v3.5'          .NET Framework 3.5
//    'v4\Client'     .NET Framework 4.0 Client Profile
//    'v4\Full'       .NET Framework 4.0 Full Installation
//    'v4.5'          .NET Framework 4.5
//
// service -- Specify any non-negative integer for the required service pack level:
//    0               No service packs required
//    1, 2, etc.      Service pack 1, 2, etc. required
var
    key: string;
    install, release, serviceCount: cardinal;
    check45, success: boolean;
begin
    // .NET 4.5 installs as update to .NET 4.0 Full
    if version = 'v4.5' then begin
        version := 'v4\Full';
        check45 := true;
    end else
        check45 := false;

    // installation key group for all .NET versions
    key := 'SOFTWARE\Microsoft\NET Framework Setup\NDP\' + version;

    // .NET 3.0 uses value InstallSuccess in subkey Setup
    if Pos('v3.0', version) = 1 then begin
        success := RegQueryDWordValue(HKLM, key + '\Setup', 'InstallSuccess', install);
    end else begin
        success := RegQueryDWordValue(HKLM, key, 'Install', install);
    end;

    // .NET 4.0/4.5 uses value Servicing instead of SP
    if Pos('v4', version) = 1 then begin
        success := success and RegQueryDWordValue(HKLM, key, 'Servicing', serviceCount);
    end else begin
        success := success and RegQueryDWordValue(HKLM, key, 'SP', serviceCount);
    end;

    // .NET 4.5 uses additional value Release
    if check45 then begin
        success := success and RegQueryDWordValue(HKLM, key, 'Release', release);
        success := success and (release >= 378389);
    end;

    result := success and (install = 1) and (serviceCount >= service);
end;


change version and add multithreaded compression

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

#define MyAppName "AnnwvynSDK"
#define MyAppVersion "0.1.7"
#define MyAppPublisher "Arthur (Ybalrid) Brainville"
#define MyAppURL "http://annwvyn.org/"

[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.)
CompressionThreads=8
AppId={{90C38FF0-25F4-454E-8152-54B4B60518BC}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName=C:\Oculus\{#MyAppName}
DefaultGroupName={#MyAppName}
AllowNoIcons=yes
LicenseFile=C:\Oculus\AnnwvynSDK\Annwvyn\LICENSE
InfoAfterFile=C:\Oculus\AnnwvynSDK\README.TXT
OutputDir=C:\Oculus\AnnwvynSetup
OutputBaseFilename=setupAnnwvynSDK
Compression=lzma
SolidCompression=yes

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

[Files]
Source: "C:\Oculus\AnnwvynSDK\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
;Source: "C:\Oculus\AnnwvynSDK\AL\*" DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
;Source: "C:\Oculus\AnnwvynSDK\README.TXT"; DestDir: "{app}"; Flags: ignoreversion
;Source: "C:\Oculus\AnnwvynSDK\RUNME.BAT"; DestDir: "{app}"; Flags: ignoreversion
;Source: "C:\Oculus\AnnwvynSDK\Annwvyn\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
;Source: "C:\Oculus\AnnwvynSDK\AnnwvynEditor\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
;Source: "C:\Oculus\AnnwvynSDK\bullet3\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
;Source: "C:\Oculus\AnnwvynSDK\glew\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
;Source: "C:\Oculus\AnnwvynSDK\libsndfile\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
;Source: "C:\Oculus\AnnwvynSDK\OculusSDK\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
;Source: "C:\Oculus\AnnwvynSDK\OgreSDK\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
;Source: "C:\Oculus\AnnwvynSDK\OIS\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
;Source: "C:\OgreCommandLineTools\*"; DestDir: "{sd}"; Flags: ignoreversion recursesubdirs createallsubdirs
; NOTE: Don't use "Flags: ignoreversion" on any shared system files

[Icons]
Name: "{group}\{cm:ProgramOnTheWeb,{#MyAppName}}"; Filename: "{#MyAppURL}"
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"

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

#define MyAppName "AnnwvynSDK"
#define MyAppVersion "0.1.2"
#define MyAppPublisher "Arthur (Ybalrid) Brainville"
#define MyAppURL "http://annwvyn.org/"

[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={{90C38FF0-25F4-454E-8152-54B4B60518BC}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName=C:\Oculus\{#MyAppName}
DefaultGroupName={#MyAppName}
AllowNoIcons=yes
LicenseFile=C:\Oculus\AnnwvynSDK\Annwvyn\LICENSE
InfoAfterFile=C:\Oculus\AnnwvynSDK\README.TXT
OutputDir=C:\Oculus\AnnwvynSetup
OutputBaseFilename=setupAnnwvynSDK
Compression=lzma
SolidCompression=yes

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

[Files]
Source: "C:\Oculus\AnnwvynSDK\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
;Source: "C:\Oculus\AnnwvynSDK\AL\*" DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
;Source: "C:\Oculus\AnnwvynSDK\README.TXT"; DestDir: "{app}"; Flags: ignoreversion
;Source: "C:\Oculus\AnnwvynSDK\RUNME.BAT"; DestDir: "{app}"; Flags: ignoreversion
;Source: "C:\Oculus\AnnwvynSDK\Annwvyn\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
;Source: "C:\Oculus\AnnwvynSDK\AnnwvynEditor\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
;Source: "C:\Oculus\AnnwvynSDK\bullet3\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
;Source: "C:\Oculus\AnnwvynSDK\glew\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
;Source: "C:\Oculus\AnnwvynSDK\libsndfile\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
;Source: "C:\Oculus\AnnwvynSDK\OculusSDK\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
;Source: "C:\Oculus\AnnwvynSDK\OgreSDK\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
;Source: "C:\Oculus\AnnwvynSDK\OIS\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
;Source: "C:\OgreCommandLineTools\*"; DestDir: "{sd}"; Flags: ignoreversion recursesubdirs createallsubdirs
; NOTE: Don't use "Flags: ignoreversion" on any shared system files

[Icons]
Name: "{group}\{cm:ProgramOnTheWeb,{#MyAppName}}"; Filename: "{#MyAppURL}"
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"