Changed copyright string in installer

Changed copyright string in installer

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

#define MyAppName "vJoy Device Driver"
#define MyShortAppName "vJoy"
#define MyAppPublisher "Shaul Eizikovich"
#define MyAppURL "http://vjoystick.sourceforge.net"
#define AppGUID "{{8E31F76F-74C3-47F1-9550-E041EEDC5FBB}"

#define vJoyInstx86 ".\objfre_wxp_x86\i386"
#define vJoyInstx64 ".\objfre_wlh_amd64\amd64"
#define vJoyLibx86 "..\lib\objfre_wxp_x86\i386"
#define vJoyLibx64 "..\lib\objfre_wlh_amd64\amd64"
#define vJoyConfDirx86 "..\apps\vJoyConf\objfre_wxp_x86\i386"
#define vJoyConfDirx64 "..\apps\vJoyConf\objfre_wlh_amd64\amd64"
#define vJoyConfigDirx86 "..\apps\vJoyConf\vJoyConfig\objfre_wxp_x86\i386"
#define vJoyConfigDirx64 "..\apps\vJoyConf\vJoyConfig\objfre_wlh_amd64\amd64"
#define vJoyFeederDirx86 "..\apps\vJoyFeeder\objfre_wxp_x86\i386"
#define vJoyFeederDirx64 "..\apps\vJoyFeeder\objfre_wlh_amd64\amd64"
#define vJoyMonDirx86 "..\apps\External\JoyMonitor\x86"
#define vJoyMonDirx64 "..\apps\External\JoyMonitor\x64"
#define vJoyDllDirx64 "..\apps\External\DLL\x64"
#define vJoyDllDirx86 "..\apps\External\DLL\x86"
#define vJoyIconFile "..\apps\vJoyInstall\GTK\Joystick-icon.ico"

#define DestSubDirX86 "x86"
#define DestSubDirX64 "x64"
#define RegLocDirX86 "DllX86Location"
#define RegLocDirX64 "DllX64Location"

; Get product version from the driver (vJoy.sys)
#define SrcDrv vJoyInstx64+"\vJoy.sys"
#define FileVerStr GetFileVersion(SrcDrv)
#define StripBuild(str VerStr) Copy(VerStr, 1)
#define DrvVerStr StripBuild(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={code:GetAppId}
AppName={#MyAppName}
AppVersion={#DrvVerStr}
VersionInfoVersion={#DrvVerStr}
AppVerName= {#MyAppName} {#DrvVerStr}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
CreateAppDir=true
OutputDir=.
OutputBaseFilename=vJoyInstallerSigned
SetupIconFile=..\apps\vJoyInstall\GTK\install.ico
Compression=lzma/Max
SolidCompression=true
DefaultDirName={pf}\{#MyShortAppName}
DefaultGroupName={#MyShortAppName}
VersionInfoCompany=Shaul Eizikovich
AppCopyright=Copyright (c) 2005-2015 by Shaul Eizikovich
MinVersion = 5.1.2600sp1
SignTool=Sig sign /a /v /s My /t http://timestamp.digicert.com $f
SignedUninstaller=yes
DisableDirPage=yes
DisableProgramGroupPage=yes
DisableReadyMemo=true
DisableFinishedPage=true
PrivilegesRequired=admin
ArchitecturesInstallIn64BitMode=x64
SetupLogging=true
UsePreviousLanguage=no
Uninstallable=yes

;[Languages]
;Name: "english"; MessagesFile: "compiler:Default.isl"
;Name: "brazilianportuguese"; MessagesFile: "compiler:Languages\BrazilianPortuguese.isl"
;Name: "hebrew"; MessagesFile: "compiler:Languages\Hebrew.isl"

[Files]
;Driver
Source: "{#vJoyInstx86}\*"; DestDir: "{app}"; Flags: promptifolder; Check: IsX86
Source: "{#vJoyInstx64}\*"; DestDir: "{app}"; Flags: promptifolder; Check: IsX64
; DLLs used by applications
Source: "{#vJoyLibx86}\*.dll"; DestDir: "{app}\{#DestSubDirX86}"
Source: "{#vJoyLibx64}\*.dll"; DestDir: "{app}\{#DestSubDirX64}"; Check: IsX64
Source: "{#vJoyDllDirx86}\*.dll"; DestDir: "{app}\{#DestSubDirX86}"
Source: "{#vJoyDllDirx64}\*.dll"; DestDir: "{app}\{#DestSubDirX64}"; Check: IsX64
;Configuration application
Source: "{#vJoyConfDirx86}\vJoyConf.exe"; DestDir: "{app}\{#DestSubDirX86}"; Components: Apps\vJoyConf; Check: IsX86
Source: "{#vJoyConfDirx64}\vJoyConf.exe"; DestDir: "{app}\{#DestSubDirX64}"; Components: Apps\vJoyConf; Check: IsX64
Source: "{#vJoyConfigDirx86}\vJoyConfig.exe"; DestDir: "{app}\{#DestSubDirX86}"; Components: Apps\vJoyConf; Check: IsX86
Source: "{#vJoyConfigDirx64}\vJoyConfig.exe"; DestDir: "{app}\{#DestSubDirX64}"; Components: Apps\vJoyConf; Check: IsX64
;Demo feeder
Source: "{#vJoyFeederDirx86}\vJoyFeeder.exe"; DestDir: "{app}\{#DestSubDirX86}"; Components: Apps\vJoyFeeder ; Check: IsX86
Source: "{#vJoyFeederDirx64}\vJoyFeeder.exe"; DestDir: "{app}\{#DestSubDirX64}"; Components: Apps\vJoyFeeder ; Check: IsX64
Source: "{#vJoyFeederDirx86}\..\..\LBIndustrialCtrls.dll"; DestDir: "{app}\{#DestSubDirX86}"; Components: Apps\vJoyFeeder ; Check: IsX86
Source: "{#vJoyFeederDirx64}\..\..\LBIndustrialCtrls.dll"; DestDir: "{app}\{#DestSubDirX64}"; Components: Apps\vJoyFeeder ; Check: IsX64
; Monitor
Source: "{#vJoyMonDirx86}\JoyMonitor.exe"; DestDir: "{app}\{#DestSubDirX86}"; Components: Apps\vJoyMon; Check: IsX86
Source: "{#vJoyMonDirx64}\JoyMonitor.exe"; DestDir: "{app}\{#DestSubDirX64}"; Components: Apps\vJoyMon; Check: IsX64

[Icons]
Name: "{group}\Uninstall vJoy"; Filename: "{uninstallexe}"
Name: "{group}\Monitor vJoy"; Filename: "{app}\{#DestSubDirX86}\JoyMonitor.exe"; Components: Apps\vJoyMon  ; Check: IsX86
Name: "{group}\Configure vJoy"; Filename: "{app}\{#DestSubDirX86}\vJoyConf.exe"; Components: Apps\vJoyConf ; Check: IsX86
Name: "{group}\vJoy Feeder (Demo)"; Filename: "{app}\{#DestSubDirX86}\vJoyFeeder.exe"; Components: Apps\vJoyFeeder ; Check: IsX86
Name: "{group}\Monitor vJoy"; Filename: "{app}\{#DestSubDirX64}\JoyMonitor.exe"; Components: Apps\vJoyMon  ; Check: IsX64
Name: "{group}\Configure vJoy"; Filename: "{app}\{#DestSubDirX64}\vJoyConf.exe"; Components: Apps\vJoyConf ; Check: IsX64
Name: "{group}\vJoy Feeder (Demo)"; Filename: "{app}\{#DestSubDirX64}\vJoyFeeder.exe"; Components: Apps\vJoyFeeder ; Check: IsX64
Name: "{group}\vJoy Home"; Filename: "http://vjoystick.sourceforge.net/site"; Comment: "vJoy site"; IconFilename:  "{#vJoyIconFile}"
Name: "{group}\vJoy SDK"; Filename: "http://vjoystick.sourceforge.net/redirect_download_vJoy2SDK.php"; Comment: "vJoy SDK"; IconFilename:  "{#vJoyIconFile}"

[Run]
Filename: "{win}\regedit.exe"; Parameters: "/s vJoyInit.reg"; WorkingDir: "{src}"; Flags: runascurrentuser waituntilterminated ;Check: not InitFromRegistry
Filename: "{app}\vJoyInstall.exe"; Parameters: "I"; WorkingDir: "{app}"; Flags: waituntilterminated RunHidden; StatusMsg: "Installing vJoy device (May take up to 5 minutes)"; Check: not DelayedRestart

[UninstallRun]
Filename: {app}\vJoyInstall.exe; Parameters: C; StatusMsg: "Uninstalling vJoy device"; Flags: waituntilterminated RunHidden; WorkingDir: {app};

[Types]
Name: "Custom"; Description: "Select companion applications"; Flags: iscustom

[Components]
Name: "Apps"; Description: "Companion Applications"; Types: Custom
Name: "Apps\vJoyFeeder"; Description: "Demo vJoy Feeder application"; Types: Custom; Flags: checkablealone
Name: "Apps\vJoyConf"; Description: "vJoy Configuration application"; Types: Custom; Flags: checkablealone
Name: "Apps\vJoyMon"; Description: "vJoy Monitoring application"; Types: Custom; Flags: checkablealone

[Code]
const
  (* General *)
    ParamInitReg        = 'initreg';

	(* Messages *)
		ManuallySetTestMode = 'You cannot install vJoy on this system.'#13#13'To enable the system open a command prompt (DOS) window as Administrator.'#13'In this window type the following line:'#13#13'BCDEDIT -SET TESTSIGNING ON'#13#13'Then Restart your computer.';
		InstallGood					= 'vJoy installed successfully';
		InstallBad					= 'vJoy failed to install';
		TestModeChanged			=	'Would you like to reset your computer back to TestSigning mode OFF?'#13'This will take effect only after you restart your computer';

  (* Constants related to registry *)
    GUID_WINDOWS_BOOTMGR      = '{9DEA862C-5CDD-4E70-ACC1-F32B344D4795}';
    DefaultObjec              = '23000003';
    AllowPrereleaseSignatures = '16000049';
    BCDRoot                   = 'BCD00000000';
    UninstKey 								= 'Software\Microsoft\Windows\CurrentVersion\Uninstall\';
  	ValOrig 									= 'OrigTestMode';

    (* Constants related to two-phase installation *)
    RunOnceName = 'vJoy Setup restart';
    RunOnceKey  = 'Software\Microsoft\Windows\CurrentVersion\RunOnce';
    Ph2Flag			=	'PH2';
    Ph2Param    = ' /'+Ph2Flag+'=1';
    QuitMessageReboot = 'The installer will now set your computer to TestSigning mode. You will need to restart your computer to complete that installation.'#13#13'After restarting your computer, Setup will continue next time an administrator logs in.';
    WaitingForRestart = 'You should now restat your computer.'#13#13'Press OK then restart your computer manually'#13'Press Cancel to cancel installation';
    ErrorRunOnce      = 'Failed to update RunOnce registry entry';
    ErrorSetTestMode  = 'Failed to set computer to TestSigning Mode';

    (* Constants related to installation under SPP *)
    SppFlag		= 'SPP';
    SppParam	= ' /'+SppFlag+'=1';
    AppIdFlag	= 'ID';
    AppIdParam	= ' /'+AppIdFlag;

var
		SkipToPh2: 		boolean; (* True is installer resumes installation after Set Test mode & restart*)
		OrigTestMode:	Boolean; (* Value of the original Test Mode *)
		CalledBySpp:	Boolean; (* True is installer called by SPP Installer *)
		DldRestart:		Boolean; (* True if delayed restart requested *)

(* Forward Function declarations - Start *)
procedure CurStepChanged(CurStep: TSetupStep); Forward;
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); Forward;
function GetOrigTestMode(): Boolean; Forward;
function InitializeSetup(): Boolean; Forward;
function IsTestMode(): Boolean; Forward;
function IsVjoyInstalled(): Boolean; Forward;
function IsX64: Boolean; Forward;
function IsX86: Boolean; Forward;
function PrepareToInstall(var NeedsRestart: Boolean): String; Forward;
function ShouldSkipPage(PageID: Integer): Boolean; Forward;
function SetTestMode(value: Boolean): Boolean; Forward;
function SetTestModeOff(): Boolean; Forward;
function SetTestModeOn(): Boolean; Forward;
function GetAppId(Param: String): String; Forward;
function DelayedRestart(): Boolean; Forward;
function InitFromRegistry(): Boolean; Forward;
function GetCommandlineParam (inParam: String):String;  Forward;
(* Forward Function declarations - End *)

(* Helper Functions *)
function IsX64: Boolean;
begin
  Result := ProcessorArchitecture = paX64;
end;

function IsX86: Boolean;
begin
  Result := ProcessorArchitecture = paX86;
end;

// Test if vJoy is installed
function IsVjoyInstalled(): Boolean;
var
  Name, RegValVjoy, Path: String;
  Len: Longint;
  Res: Boolean;

begin
  RegValVjoy := 'SYSTEM\CurrentControlSet\Enum\Root\HIDCLASS\0000';
  Name := 'Service';
  Res := RegQueryStringValue(HKEY_LOCAL_MACHINE, RegValVjoy, Name, Path);
  if Res then Len := Length(Path) else Len := 0;
  if (Len > 0) then Result := true  else    Result := false;
end;

(*
  Check if computer in testsigning mode
  How:
  Go to the BCD in the registry and look for the Boot manager entry
  Inside, get the GUID of the defoalt loader.
  Inside the default loader, get the value of the testsigning mode
  Note: If does not exist = testsigning is off
  Return:
  True if testsigning is ON
  False if testsigning is OFF
*)
function IsTestMode(): Boolean;
var
  RegValDeflt, RegValTestsig, Name, Path, msg : String;
  tmp: AnsiString;
  Res: Boolean;
begin
  Log('IsTestMode: Start');

  RegValDeflt := BCDRoot + '\Objects\' + GUID_WINDOWS_BOOTMGR + '\Elements\' + DefaultObjec;
  Name := 'Element'

  // Get pointer to default loader
  Res := RegQueryStringValue(HKEY_LOCAL_MACHINE, RegValDeflt, Name, Path);
  if not Res then
    begin
    (* Debug start  *)
      msg := 'IsTestMode: Cannot find value for ' + RegValDeflt + '\' + Name;
      Log(msg);
     (*Debug end*)
      Result := False;
      exit;
    end;
  (* Debug start *)
   msg := 'IsTestMode: Got value for ' + RegValDeflt + '\' + Name +': ' + Path;
   Log(msg);
  (*  Debug end*)

  // Get testsigning value
  RegValTestsig := BCDRoot + '\Objects\' + Path + '\Elements\' + AllowPrereleaseSignatures;
  tmp := '#0';
  Res := RegQueryBinaryValue(HKEY_LOCAL_MACHINE, RegValTestsig, Name, tmp);
 (* Debug start   *)
 if Res then
 begin
  if tmp <> #0 then
   begin
   msg := 'IsTestMode: RegQueryBinaryValue for ' + RegValTestsig + '\' + NAME + ': Test mode ON ('+ tmp +')';
   Log(msg);
   end
  else
   begin
   msg := 'IsTestMode: RegQueryBinaryValue for ' + RegValTestsig + '\' + NAME + ': Test mode OFF ('+ tmp +')';
   Log(msg);
   end;
  end
 else
  begin
  msg := 'IsTestMode: RegQueryBinaryValue for ' + RegValTestsig + '\' + NAME + ': failed';
  Log(msg);
  end;

(*  Debug end *)
  if tmp = #1 then
    Result := True
  else
    Result := False;
end; // End Function IsTestMode

/////////////////////////////////////////////////////////////////////
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 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;

/////////////////////////////////////////////////////////////////////

(*
	InitializeSetup() is an event function that is
	Called during Setup's initialization.
	Setup aborted if function returns False.

	In this case:
  Always Returns True (never abort installation)

  Test command-line parameters
  If parameter PH2 exists then go directly to PrepareToInstall() (set SkipToPh2)

  If this is a call made while the computer is waiting for manual restart
  (RunOnce parameter is set) then reset status (Delete RunOnce+Reset Test mode) and continue.
*)
function InitializeSetup(): Boolean;

begin

	//MsgBox('Inside InitializeSetup()' , mbInformation, MB_OK)
	Log('InitializeSetup()');
  // Command-line parameters
    if (IsUpgrade()) then
    begin
      UnInstallOldVersion();
   end;

  Result := True;
end;

(* Pre & Post-install operations *)
procedure CurStepChanged(CurStep: TSetupStep);
begin
//	if  CurStep=ssInstall then
//		MsgBox('CurStepChanged(ssInstall)' , mbInformation, MB_OK);
//	if  CurStep=ssPostInstall then
//		MsgBox('CurStepChanged(ssPostInstall)' , mbInformation, MB_OK);
//	if  CurStep=ssDone then
//		MsgBox('CurStepChanged(ssDone)' , mbInformation, MB_OK);

// Check if this is an upgrade. If so, uninstall previous version
// From http://stackoverflow.com/questions/2000296/innosetup-how-to-automatically-uninstall-previous-installed-version#2099805
  if (CurStep=ssInstall) then
  begin
    Log('CurStepChanged(ssInstall)');
 //   if (IsUpgrade()) then
 //   begin
 //     UnInstallOldVersion();
 //  end;
  end;

	if  (CurStep=ssPostInstall) and (not CalledBySpp) then
	begin // Post install actions - check if vJoy is now installed
    Log('CurStepChanged(ssPostInstall)');
		if IsVjoyInstalled then
			MsgBox(InstallGood , mbInformation, MB_OK)
		else
			MsgBox(InstallBad , mbError, MB_OK)
	end; // Post install actions
end;

(* Pre & Post-uninstall operations *)
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
	if CurUninstallStep = usPostUninstall then
		DelTree( ExpandConstant('{app}'), True, True, True);
end;

(*
    Called by the installer just before installation
    In phase 2 it does nothing.

    If must set test mode (x64 machine that is not in test mode) then:
      Set  NeedsRestart to true
      Set Test mode
      Create RunOnce entry
      Return "Restart?" dialog box
    Else
      Set  NeedsRestart to false
*)

function PrepareToInstall(var NeedsRestart: Boolean): String;
var
  RunOnceData: String;

begin
// Default
NeedsRestart := False;
DldRestart := False;
end;

(*
  Called before every wizard page.
  Pages skipped if installer called with parameter PH2
*)
function ShouldSkipPage(PageID: Integer): Boolean;
begin
  Result := SkipToPh2;
end;

(*
  Set Testsigning mode On/Off acording to value of variable 'value'
  Executed only for x64 - else NOP (return FALSE)
  Return TRUE is succeeded
  Return FALSE if failed or if already was in the required state
*)
function SetTestMode(value: Boolean): Boolean;
var
  ResultCode: Integer;
  params: String;

Begin

  if not ProcessorArchitecture = paX64 then
  begin
   Result := false;
   //exit;
  end; // Not x64

  if (IsTestMode = value) then
  begin
   Result := false;
   exit;
  end; //  already was in the required state

   // Execute BCDEdit shell command
   if value then
    Params := ' -set TESTSIGNING ON'
   else
    Params := ' -set TESTSIGNING OFF';

   Exec('Bcdedit.exe',Params, '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
   Result := True;
end; // End Function SetTestMode

function SetTestModeOn(): Boolean;
begin
  result := SetTestMode(True);
end;

function SetTestModeOff(): Boolean;
begin
  result := SetTestMode(False);
end;

(*
  Record the original value of TestSigning in the registry for usage by uninstall
  Do NOT override original value
  Assuming that is called by the function that actually perform the operation so no testing.
  Set boolean Value:  HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{XXX}_is1\OrigTestMode
  {XXX} stands for the AppID
*)
Procedure RegWriteOrigTestMode(TestModeSet: Boolean);
var
	UninstKeyVjoy: String;

Begin

  UninstKeyVjoy := UninstKey + GetAppId('') + '_is1';

	Log('RegWriteOrigTestMode(): UninstKeyVjoy='+UninstKeyVjoy+'\'+ValOrig);
  // Test if Value exists
  if not RegValueExists(HKEY_LOCAL_MACHINE, UninstKeyVjoy, ValOrig) then
  begin // Set the Value because it does not exist
  	Log('Set the Value because it does not exist');
  	if TestModeSet then
    	RegWriteBinaryValue(HKEY_LOCAL_MACHINE, UninstKeyVjoy, ValOrig, #1)
  	else
    	RegWriteBinaryValue(HKEY_LOCAL_MACHINE, UninstKeyVjoy, ValOrig, #0);
  end; // Set the key because it does not exist
End;

(*
  Record the location of X86/X64 DLL files for use by filter applications
  Set string Value:  HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{XXX}_is1\DllX86Location\ to {app}\x86
  Set string Value:  HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{XXX}_is1\DllX64Location\ to {app}\x64
  {XXX} stands for the AppID
*)
Procedure RegWriteDllFolderLocation();
var
	UninstKeyVjoy: String;

Begin

  UninstKeyVjoy := UninstKey + GetAppId('') + '_is1';

  Log('RegWriteDllFolderLocation(): UninstKeyVjoy='+UninstKeyVjoy+'\'+'{#RegLocDirX86}');
  RegWriteStringValue(HKEY_LOCAL_MACHINE, UninstKeyVjoy, '{#RegLocDirX86}', expandconstant('{app}')+'\'+'{#DestSubDirX86}')
  if IsX64 then
    begin
    Log('RegWriteDllFolderLocation(): UninstKeyVjoy='+UninstKeyVjoy+'\'+'{#RegLocDirX64}');
    RegWriteStringValue(HKEY_LOCAL_MACHINE, UninstKeyVjoy, '{#RegLocDirX64}', expandconstant('{app}')+'\'+'{#DestSubDirX64}')
    end;
End;

(*
    This is called just on the way out of the wizard
    The app Uninstall registry entry already exists
*)
procedure DeinitializeSetup();
begin
  (*
  	Write the original value of Test Mode to the Registry
  	If this is the second step it must be '0'
  	Otherwise we don't care.
  *)
  //MsgBox('Inside DeinitializeSetup()' , mbInformation, MB_OK)
	  RegWriteOrigTestMode(OrigTestMode);

  (* Write directory locations to the registry *)
  RegWriteDllFolderLocation();

end;

(*
	Get the original value of Test Mode - call it on InitializeSetup()

	There are 4 cases:
	1. Check if this is Phase2. If it is then the original value was False.
	2. If this is not Phase2, this might be repetition of the first phase:
	   The RunOnce registry entry is set to /PH2=1 so the original value is False.
	3. This can be a new installation over an already installed vJoy:
	   check the value in the registry (inside the appropriate Uninstall key).
	4. If this value does not exist check the current test mode.

  Keep the value for use in the ssPostInstall step.
*)
function GetOrigTestMode(): Boolean;
var
	data: String;
	UninstKeyVjoy: String;
	Adata: AnsiString;

begin
	(* Case 1 *)
	if ExpandConstant('{param:'+Ph2Flag+'|0}') = '1' then
		begin	// Case 1
			Log('GetOrigTestMode(): Case 1');
			Result := false;
			exit;
		end;	// Case 1

	(* Case 2 *)
	if RegQueryStringValue(HKLM, RunOnceKey, RunOnceName, data) then
		begin // Case 1/2
			Log('GetOrigTestMode(): RunOnce String is: '+ data);
			if Pos(Ph2Param,data) > 0  then
			begin	// Found PH2
				Log('GetOrigTestMode(): "PH2" was found in RunOnce key');
				Result := false;
				exit;
			end		// Found PH2
		end;	// Case 1/2

	(* Case 3 *)
  UninstKeyVjoy := UninstKey + GetAppId('')  + '_is1';
  if RegQueryBinaryValue(HKEY_LOCAL_MACHINE, UninstKeyVjoy, ValOrig, Adata) then
  	begin // Case 3
  	if Adata = #1 then
  		Result := true
  	else
  		Result := false;
  		Log('GetOrigTestMode(): Found entry in '+ UninstKeyVjoy);
  	exit;
  	end;	// Case 3

  	(* Case 4 *)
		Log('GetOrigTestMode(): call IsTestMode()');
  	Result := IsTestMode;

end;

(*
	Called when starting uninstall

	Check if need to Revert Test Mode to OFF
*)
function InitializeUninstall(): Boolean;
var
	UninstKeyVjoy: String;
	Adata: AnsiString;

begin
  Result := true				// Default
  OrigTestMode := true; // Default
	UninstKeyVjoy := UninstKey + GetAppId('') + '_is1';

  if RegQueryBinaryValue(HKEY_LOCAL_MACHINE, UninstKeyVjoy, ValOrig, Adata) then
  	begin
  		Log('InitializeUninstall(): Found entry in '+ UninstKeyVjoy);
  		if Adata = #0 then
  			OrigTestMode := false;
  	end;
end;

(*
	Need restart if the user choses to reset Test Mode
*)
function UninstallNeedRestart(): Boolean;
var
	ResetTestMode: Integer;

begin
	Result := False; // Defaul

	if (OrigTestMode = false) and  IsTestMode then
	begin // Test Mode Changed
		ResetTestMode := MsgBox(TestModeChanged, mbConfirmation, MB_YESNO);
		if ResetTestMode = IDYES then
		begin	// Reset Test Mode
			SetTestModeOff();
			result := True;
		end;	// Reset Test Mode
	end;  // Test Mode Changed
end;

(*
  Get AppID from command line parameter ID (/ID=ABC)
  If this parameter is missing use AppGUID constant
*)
function GetAppId(Param: String): String;
begin
 Result := ExpandConstant('{param:'+AppIdFlag+'}');
  if Length(Result)=0 then
    Result :=  expandconstant('{#AppGUID}');;

end;

function DelayedRestart(): Boolean;
begin
	Result:= DldRestart;
end;

(*
			If delayed restart needed then change exit value
*)
function GetCustomSetupExitCode: Integer;
begin
	if DldRestart then Result := 8;
end;

(*
    Normalize Flag:
    Remove one leading flag-sign: Slash(/) or Minus(-) - If missing return empty string
    Convert to lower case
*)
function  NormalizeFlag (inFlag : String) : String;

begin
    Result :=  '';
// Check length
    if (Length(inFlag) <2) then exit;

// Remove the first character if it '/' or '-'
    Result :=  inFlag;
    Delete(Result, 1, 1)

// Convert to lower case
    Result := Lowercase(Result);

end;

(*
    Allows for standard command line parsing assuming a key/value organization
    Based on:  http://stackoverflow.com/questions/3618257/is-it-possible-to-accept-custom-command-line-parameters-with-innosetup
*)
function GetCommandlineParam (inParam: String):String;
var
  LoopVar : Integer;
  BreakLoop : Boolean;
  strParam : String;

begin
  { Init the variable to known values }
  LoopVar :=0;
  Result := '';
  BreakLoop := False;

  { Loop through the passed in arry to find the parameter }
  while ( (LoopVar < ParamCount) and (not BreakLoop) ) do
  begin

  strParam := NormalizeFlag(ParamStr(LoopVar));

    { Determine if the looked for parameter is the next value }
    if ( (strParam = inParam) and ( (LoopVar+1) <= ParamCount )) then
    begin
      { Set the return result equal to the next command line parameter }
      Result := ParamStr(LoopVar+1);

      { Break the loop }
      BreakLoop := True;
      Log('GetCommandlineParam(): Flag: '+ inParam + ' Value: ' + Result);
    end;

    { Increment the loop variable }
    LoopVar := LoopVar + 1;
  end;

  if (BreakLoop = False) then Log('GetCommandlineParam(): Flag: '+ inParam + ' not found');
end;

(*
    Gets from the command line the name of the file to merge into the registry
    If exists returns TRUE else FALSE
*)
function InitFromRegistry(): Boolean;
var
  FileName : String ;
  ResultCode: Integer;
begin
  Result := FALSE;

  // Gets the file name - exit with FALSE if fails
  FileName :=  GetCommandlineParam(ParamInitReg);
  if (Length(FileName) = 0 )   then exit;

  // Merge file to registry
  if (not FileExists(ExpandConstant('{src}\'+FileName))) then
    begin
      Log('InitFromRegistry(): File' + ExpandConstant('{src}\'+FileName) + ' not found');
      exit;
    end;

  if Exec(ExpandConstant('{win}\regedit.exe'), '/s ' + FileName, ExpandConstant('{src}'), SW_HIDE, ewWaitUntilTerminated, ResultCode) then   Result := TRUE;

  if (Result = TRUE) then
        Log('InitFromRegistry(): Merging file  ' + FileName + ' into the registry - code: ' + IntToStr(ResultCode))
  else
        Log('InitFromRegistry(): Merging file  ' + FileName + ' into the registry - Failed');

end;

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

#define MyAppName "vJoy Device Driver"
#define MyShortAppName "vJoy"
#define MyAppPublisher "Shaul Eizikovich"
#define MyAppURL "http://vjoystick.sourceforge.net"
#define AppGUID "{{8E31F76F-74C3-47F1-9550-E041EEDC5FBB}"

#define vJoyInstx86 ".\objfre_wxp_x86\i386"
#define vJoyInstx64 ".\objfre_wlh_amd64\amd64"
#define vJoyLibx86 "..\lib\objfre_wxp_x86\i386"
#define vJoyLibx64 "..\lib\objfre_wlh_amd64\amd64"
#define vJoyConfDirx86 "..\apps\vJoyConf\objfre_wxp_x86\i386"
#define vJoyConfDirx64 "..\apps\vJoyConf\objfre_wlh_amd64\amd64"
#define vJoyConfigDirx86 "..\apps\vJoyConf\vJoyConfig\objfre_wxp_x86\i386"
#define vJoyConfigDirx64 "..\apps\vJoyConf\vJoyConfig\objfre_wlh_amd64\amd64"
#define vJoyFeederDirx86 "..\apps\vJoyFeeder\objfre_wxp_x86\i386"
#define vJoyFeederDirx64 "..\apps\vJoyFeeder\objfre_wlh_amd64\amd64"
#define vJoyMonDirx86 "..\apps\External\JoyMonitor\x86"
#define vJoyMonDirx64 "..\apps\External\JoyMonitor\x64"
#define vJoyDllDirx64 "..\apps\External\DLL\x64"
#define vJoyDllDirx86 "..\apps\External\DLL\x86"
#define vJoyIconFile "..\apps\vJoyInstall\GTK\Joystick-icon.ico"

#define DestSubDirX86 "x86"
#define DestSubDirX64 "x64"
#define RegLocDirX86 "DllX86Location"
#define RegLocDirX64 "DllX64Location"

; Get product version from the driver (vJoy.sys)
#define SrcDrv vJoyInstx64+"\vJoy.sys"
#define FileVerStr GetFileVersion(SrcDrv)
#define StripBuild(str VerStr) Copy(VerStr, 1)
#define DrvVerStr StripBuild(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={code:GetAppId}
AppName={#MyAppName}
AppVersion={#DrvVerStr}
VersionInfoVersion={#DrvVerStr}
AppVerName= {#MyAppName} {#DrvVerStr}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
CreateAppDir=true
OutputDir=.
OutputBaseFilename=vJoyInstallerSigned
SetupIconFile=..\apps\vJoyInstall\GTK\install.ico
Compression=lzma/Max
SolidCompression=true
DefaultDirName={pf}\{#MyShortAppName}
DefaultGroupName={#MyShortAppName}
VersionInfoCompany=Shaul Eizikovich
AppCopyright=Copyright (c) 2005-2014 by Shaul Eizikovich
MinVersion = 5.1.2600sp1
SignTool=Sig sign /a /v /s My /t http://timestamp.digicert.com $f
SignedUninstaller=yes
DisableDirPage=yes
DisableProgramGroupPage=yes
DisableReadyMemo=true
DisableFinishedPage=true
PrivilegesRequired=admin
ArchitecturesInstallIn64BitMode=x64
SetupLogging=true
UsePreviousLanguage=no
Uninstallable=yes

;[Languages]
;Name: "english"; MessagesFile: "compiler:Default.isl"
;Name: "brazilianportuguese"; MessagesFile: "compiler:Languages\BrazilianPortuguese.isl"
;Name: "hebrew"; MessagesFile: "compiler:Languages\Hebrew.isl"

[Files]
;Driver
Source: "{#vJoyInstx86}\*"; DestDir: "{app}"; Flags: promptifolder; Check: IsX86
Source: "{#vJoyInstx64}\*"; DestDir: "{app}"; Flags: promptifolder; Check: IsX64
; DLLs used by applications
Source: "{#vJoyLibx86}\*.dll"; DestDir: "{app}\{#DestSubDirX86}"
Source: "{#vJoyLibx64}\*.dll"; DestDir: "{app}\{#DestSubDirX64}"; Check: IsX64
Source: "{#vJoyDllDirx86}\*.dll"; DestDir: "{app}\{#DestSubDirX86}"
Source: "{#vJoyDllDirx64}\*.dll"; DestDir: "{app}\{#DestSubDirX64}"; Check: IsX64
;Configuration application
Source: "{#vJoyConfDirx86}\vJoyConf.exe"; DestDir: "{app}\{#DestSubDirX86}"; Components: Apps\vJoyConf; Check: IsX86
Source: "{#vJoyConfDirx64}\vJoyConf.exe"; DestDir: "{app}\{#DestSubDirX64}"; Components: Apps\vJoyConf; Check: IsX64
Source: "{#vJoyConfigDirx86}\vJoyConfig.exe"; DestDir: "{app}\{#DestSubDirX86}"; Components: Apps\vJoyConf; Check: IsX86
Source: "{#vJoyConfigDirx64}\vJoyConfig.exe"; DestDir: "{app}\{#DestSubDirX64}"; Components: Apps\vJoyConf; Check: IsX64
;Demo feeder
Source: "{#vJoyFeederDirx86}\vJoyFeeder.exe"; DestDir: "{app}\{#DestSubDirX86}"; Components: Apps\vJoyFeeder ; Check: IsX86
Source: "{#vJoyFeederDirx64}\vJoyFeeder.exe"; DestDir: "{app}\{#DestSubDirX64}"; Components: Apps\vJoyFeeder ; Check: IsX64
Source: "{#vJoyFeederDirx86}\..\..\LBIndustrialCtrls.dll"; DestDir: "{app}\{#DestSubDirX86}"; Components: Apps\vJoyFeeder ; Check: IsX86
Source: "{#vJoyFeederDirx64}\..\..\LBIndustrialCtrls.dll"; DestDir: "{app}\{#DestSubDirX64}"; Components: Apps\vJoyFeeder ; Check: IsX64
; Monitor
Source: "{#vJoyMonDirx86}\JoyMonitor.exe"; DestDir: "{app}\{#DestSubDirX86}"; Components: Apps\vJoyMon; Check: IsX86
Source: "{#vJoyMonDirx64}\JoyMonitor.exe"; DestDir: "{app}\{#DestSubDirX64}"; Components: Apps\vJoyMon; Check: IsX64

[Icons]
Name: "{group}\Uninstall vJoy"; Filename: "{uninstallexe}"
Name: "{group}\Monitor vJoy"; Filename: "{app}\{#DestSubDirX86}\JoyMonitor.exe"; Components: Apps\vJoyMon  ; Check: IsX86
Name: "{group}\Configure vJoy"; Filename: "{app}\{#DestSubDirX86}\vJoyConf.exe"; Components: Apps\vJoyConf ; Check: IsX86
Name: "{group}\vJoy Feeder (Demo)"; Filename: "{app}\{#DestSubDirX86}\vJoyFeeder.exe"; Components: Apps\vJoyFeeder ; Check: IsX86
Name: "{group}\Monitor vJoy"; Filename: "{app}\{#DestSubDirX64}\JoyMonitor.exe"; Components: Apps\vJoyMon  ; Check: IsX64
Name: "{group}\Configure vJoy"; Filename: "{app}\{#DestSubDirX64}\vJoyConf.exe"; Components: Apps\vJoyConf ; Check: IsX64
Name: "{group}\vJoy Feeder (Demo)"; Filename: "{app}\{#DestSubDirX64}\vJoyFeeder.exe"; Components: Apps\vJoyFeeder ; Check: IsX64
Name: "{group}\vJoy Home"; Filename: "http://vjoystick.sourceforge.net/site"; Comment: "vJoy site"; IconFilename:  "{#vJoyIconFile}"
Name: "{group}\vJoy SDK"; Filename: "http://vjoystick.sourceforge.net/redirect_download_vJoy2SDK.php"; Comment: "vJoy SDK"; IconFilename:  "{#vJoyIconFile}"

[Run]
Filename: "{win}\regedit.exe"; Parameters: "/s vJoyInit.reg"; WorkingDir: "{src}"; Flags: runascurrentuser waituntilterminated ;Check: not InitFromRegistry
Filename: "{app}\vJoyInstall.exe"; Parameters: "I"; WorkingDir: "{app}"; Flags: waituntilterminated RunHidden; StatusMsg: "Installing vJoy device (May take up to 5 minutes)"; Check: not DelayedRestart

[UninstallRun]
Filename: {app}\vJoyInstall.exe; Parameters: C; StatusMsg: "Uninstalling vJoy device"; Flags: waituntilterminated RunHidden; WorkingDir: {app};

[Types]
Name: "Custom"; Description: "Select companion applications"; Flags: iscustom

[Components]
Name: "Apps"; Description: "Companion Applications"; Types: Custom
Name: "Apps\vJoyFeeder"; Description: "Demo vJoy Feeder application"; Types: Custom; Flags: checkablealone
Name: "Apps\vJoyConf"; Description: "vJoy Configuration application"; Types: Custom; Flags: checkablealone
Name: "Apps\vJoyMon"; Description: "vJoy Monitoring application"; Types: Custom; Flags: checkablealone

[Code]
const
  (* General *)
    ParamInitReg        = 'initreg';

	(* Messages *)
		ManuallySetTestMode = 'You cannot install vJoy on this system.'#13#13'To enable the system open a command prompt (DOS) window as Administrator.'#13'In this window type the following line:'#13#13'BCDEDIT -SET TESTSIGNING ON'#13#13'Then Restart your computer.';
		InstallGood					= 'vJoy installed successfully';
		InstallBad					= 'vJoy failed to install';
		TestModeChanged			=	'Would you like to reset your computer back to TestSigning mode OFF?'#13'This will take effect only after you restart your computer';

  (* Constants related to registry *)
    GUID_WINDOWS_BOOTMGR      = '{9DEA862C-5CDD-4E70-ACC1-F32B344D4795}';
    DefaultObjec              = '23000003';
    AllowPrereleaseSignatures = '16000049';
    BCDRoot                   = 'BCD00000000';
    UninstKey 								= 'Software\Microsoft\Windows\CurrentVersion\Uninstall\';
  	ValOrig 									= 'OrigTestMode';

    (* Constants related to two-phase installation *)
    RunOnceName = 'vJoy Setup restart';
    RunOnceKey  = 'Software\Microsoft\Windows\CurrentVersion\RunOnce';
    Ph2Flag			=	'PH2';
    Ph2Param    = ' /'+Ph2Flag+'=1';
    QuitMessageReboot = 'The installer will now set your computer to TestSigning mode. You will need to restart your computer to complete that installation.'#13#13'After restarting your computer, Setup will continue next time an administrator logs in.';
    WaitingForRestart = 'You should now restat your computer.'#13#13'Press OK then restart your computer manually'#13'Press Cancel to cancel installation';
    ErrorRunOnce      = 'Failed to update RunOnce registry entry';
    ErrorSetTestMode  = 'Failed to set computer to TestSigning Mode';

    (* Constants related to installation under SPP *)
    SppFlag		= 'SPP';
    SppParam	= ' /'+SppFlag+'=1';
    AppIdFlag	= 'ID';
    AppIdParam	= ' /'+AppIdFlag;

var
		SkipToPh2: 		boolean; (* True is installer resumes installation after Set Test mode & restart*)
		OrigTestMode:	Boolean; (* Value of the original Test Mode *)
		CalledBySpp:	Boolean; (* True is installer called by SPP Installer *)
		DldRestart:		Boolean; (* True if delayed restart requested *)

(* Forward Function declarations - Start *)
procedure CurStepChanged(CurStep: TSetupStep); Forward;
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); Forward;
function GetOrigTestMode(): Boolean; Forward;
function InitializeSetup(): Boolean; Forward;
function IsTestMode(): Boolean; Forward;
function IsVjoyInstalled(): Boolean; Forward;
function IsX64: Boolean; Forward;
function IsX86: Boolean; Forward;
function PrepareToInstall(var NeedsRestart: Boolean): String; Forward;
function ShouldSkipPage(PageID: Integer): Boolean; Forward;
function SetTestMode(value: Boolean): Boolean; Forward;
function SetTestModeOff(): Boolean; Forward;
function SetTestModeOn(): Boolean; Forward;
function GetAppId(Param: String): String; Forward;
function DelayedRestart(): Boolean; Forward;
function InitFromRegistry(): Boolean; Forward;
function GetCommandlineParam (inParam: String):String;  Forward;
(* Forward Function declarations - End *)

(* Helper Functions *)
function IsX64: Boolean;
begin
  Result := ProcessorArchitecture = paX64;
end;

function IsX86: Boolean;
begin
  Result := ProcessorArchitecture = paX86;
end;

// Test if vJoy is installed
function IsVjoyInstalled(): Boolean;
var
  Name, RegValVjoy, Path: String;
  Len: Longint;
  Res: Boolean;

begin
  RegValVjoy := 'SYSTEM\CurrentControlSet\Enum\Root\HIDCLASS\0000';
  Name := 'Service';
  Res := RegQueryStringValue(HKEY_LOCAL_MACHINE, RegValVjoy, Name, Path);
  if Res then Len := Length(Path) else Len := 0;
  if (Len > 0) then Result := true  else    Result := false;
end;

(*
  Check if computer in testsigning mode
  How:
  Go to the BCD in the registry and look for the Boot manager entry
  Inside, get the GUID of the defoalt loader.
  Inside the default loader, get the value of the testsigning mode
  Note: If does not exist = testsigning is off
  Return:
  True if testsigning is ON
  False if testsigning is OFF
*)
function IsTestMode(): Boolean;
var
  RegValDeflt, RegValTestsig, Name, Path, msg : String;
  tmp: AnsiString;
  Res: Boolean;
begin
  Log('IsTestMode: Start');

  RegValDeflt := BCDRoot + '\Objects\' + GUID_WINDOWS_BOOTMGR + '\Elements\' + DefaultObjec;
  Name := 'Element'

  // Get pointer to default loader
  Res := RegQueryStringValue(HKEY_LOCAL_MACHINE, RegValDeflt, Name, Path);
  if not Res then
    begin
    (* Debug start  *)
      msg := 'IsTestMode: Cannot find value for ' + RegValDeflt + '\' + Name;
      Log(msg);
     (*Debug end*)
      Result := False;
      exit;
    end;
  (* Debug start *)
   msg := 'IsTestMode: Got value for ' + RegValDeflt + '\' + Name +': ' + Path;
   Log(msg);
  (*  Debug end*)

  // Get testsigning value
  RegValTestsig := BCDRoot + '\Objects\' + Path + '\Elements\' + AllowPrereleaseSignatures;
  tmp := '#0';
  Res := RegQueryBinaryValue(HKEY_LOCAL_MACHINE, RegValTestsig, Name, tmp);
 (* Debug start   *)
 if Res then
 begin
  if tmp <> #0 then
   begin
   msg := 'IsTestMode: RegQueryBinaryValue for ' + RegValTestsig + '\' + NAME + ': Test mode ON ('+ tmp +')';
   Log(msg);
   end
  else
   begin
   msg := 'IsTestMode: RegQueryBinaryValue for ' + RegValTestsig + '\' + NAME + ': Test mode OFF ('+ tmp +')';
   Log(msg);
   end;
  end
 else
  begin
  msg := 'IsTestMode: RegQueryBinaryValue for ' + RegValTestsig + '\' + NAME + ': failed';
  Log(msg);
  end;

(*  Debug end *)
  if tmp = #1 then
    Result := True
  else
    Result := False;
end; // End Function IsTestMode

/////////////////////////////////////////////////////////////////////
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 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;

/////////////////////////////////////////////////////////////////////

(*
	InitializeSetup() is an event function that is
	Called during Setup's initialization.
	Setup aborted if function returns False.

	In this case:
  Always Returns True (never abort installation)

  Test command-line parameters
  If parameter PH2 exists then go directly to PrepareToInstall() (set SkipToPh2)

  If this is a call made while the computer is waiting for manual restart
  (RunOnce parameter is set) then reset status (Delete RunOnce+Reset Test mode) and continue.
*)
function InitializeSetup(): Boolean;

begin

	//MsgBox('Inside InitializeSetup()' , mbInformation, MB_OK)
	Log('InitializeSetup()');
  // Command-line parameters
    if (IsUpgrade()) then
    begin
      UnInstallOldVersion();
   end;

  Result := True;
end;

(* Pre & Post-install operations *)
procedure CurStepChanged(CurStep: TSetupStep);
begin
//	if  CurStep=ssInstall then
//		MsgBox('CurStepChanged(ssInstall)' , mbInformation, MB_OK);
//	if  CurStep=ssPostInstall then
//		MsgBox('CurStepChanged(ssPostInstall)' , mbInformation, MB_OK);
//	if  CurStep=ssDone then
//		MsgBox('CurStepChanged(ssDone)' , mbInformation, MB_OK);

// Check if this is an upgrade. If so, uninstall previous version
// From http://stackoverflow.com/questions/2000296/innosetup-how-to-automatically-uninstall-previous-installed-version#2099805
  if (CurStep=ssInstall) then
  begin
    Log('CurStepChanged(ssInstall)');
 //   if (IsUpgrade()) then
 //   begin
 //     UnInstallOldVersion();
 //  end;
  end;

	if  (CurStep=ssPostInstall) and (not CalledBySpp) then
	begin // Post install actions - check if vJoy is now installed
    Log('CurStepChanged(ssPostInstall)');
		if IsVjoyInstalled then
			MsgBox(InstallGood , mbInformation, MB_OK)
		else
			MsgBox(InstallBad , mbError, MB_OK)
	end; // Post install actions
end;

(* Pre & Post-uninstall operations *)
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
	if CurUninstallStep = usPostUninstall then
		DelTree( ExpandConstant('{app}'), True, True, True);
end;

(*
    Called by the installer just before installation
    In phase 2 it does nothing.

    If must set test mode (x64 machine that is not in test mode) then:
      Set  NeedsRestart to true
      Set Test mode
      Create RunOnce entry
      Return "Restart?" dialog box
    Else
      Set  NeedsRestart to false
*)

function PrepareToInstall(var NeedsRestart: Boolean): String;
var
  RunOnceData: String;

begin
// Default
NeedsRestart := False;
DldRestart := False;
end;

(*
  Called before every wizard page.
  Pages skipped if installer called with parameter PH2
*)
function ShouldSkipPage(PageID: Integer): Boolean;
begin
  Result := SkipToPh2;
end;

(*
  Set Testsigning mode On/Off acording to value of variable 'value'
  Executed only for x64 - else NOP (return FALSE)
  Return TRUE is succeeded
  Return FALSE if failed or if already was in the required state
*)
function SetTestMode(value: Boolean): Boolean;
var
  ResultCode: Integer;
  params: String;

Begin

  if not ProcessorArchitecture = paX64 then
  begin
   Result := false;
   //exit;
  end; // Not x64

  if (IsTestMode = value) then
  begin
   Result := false;
   exit;
  end; //  already was in the required state

   // Execute BCDEdit shell command
   if value then
    Params := ' -set TESTSIGNING ON'
   else
    Params := ' -set TESTSIGNING OFF';

   Exec('Bcdedit.exe',Params, '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
   Result := True;
end; // End Function SetTestMode

function SetTestModeOn(): Boolean;
begin
  result := SetTestMode(True);
end;

function SetTestModeOff(): Boolean;
begin
  result := SetTestMode(False);
end;

(*
  Record the original value of TestSigning in the registry for usage by uninstall
  Do NOT override original value
  Assuming that is called by the function that actually perform the operation so no testing.
  Set boolean Value:  HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{XXX}_is1\OrigTestMode
  {XXX} stands for the AppID
*)
Procedure RegWriteOrigTestMode(TestModeSet: Boolean);
var
	UninstKeyVjoy: String;

Begin

  UninstKeyVjoy := UninstKey + GetAppId('') + '_is1';

	Log('RegWriteOrigTestMode(): UninstKeyVjoy='+UninstKeyVjoy+'\'+ValOrig);
  // Test if Value exists
  if not RegValueExists(HKEY_LOCAL_MACHINE, UninstKeyVjoy, ValOrig) then
  begin // Set the Value because it does not exist
  	Log('Set the Value because it does not exist');
  	if TestModeSet then
    	RegWriteBinaryValue(HKEY_LOCAL_MACHINE, UninstKeyVjoy, ValOrig, #1)
  	else
    	RegWriteBinaryValue(HKEY_LOCAL_MACHINE, UninstKeyVjoy, ValOrig, #0);
  end; // Set the key because it does not exist
End;

(*
  Record the location of X86/X64 DLL files for use by filter applications
  Set string Value:  HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{XXX}_is1\DllX86Location\ to {app}\x86
  Set string Value:  HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{XXX}_is1\DllX64Location\ to {app}\x64
  {XXX} stands for the AppID
*)
Procedure RegWriteDllFolderLocation();
var
	UninstKeyVjoy: String;

Begin

  UninstKeyVjoy := UninstKey + GetAppId('') + '_is1';

  Log('RegWriteDllFolderLocation(): UninstKeyVjoy='+UninstKeyVjoy+'\'+'{#RegLocDirX86}');
  RegWriteStringValue(HKEY_LOCAL_MACHINE, UninstKeyVjoy, '{#RegLocDirX86}', expandconstant('{app}')+'\'+'{#DestSubDirX86}')
  if IsX64 then
    begin
    Log('RegWriteDllFolderLocation(): UninstKeyVjoy='+UninstKeyVjoy+'\'+'{#RegLocDirX64}');
    RegWriteStringValue(HKEY_LOCAL_MACHINE, UninstKeyVjoy, '{#RegLocDirX64}', expandconstant('{app}')+'\'+'{#DestSubDirX64}')
    end;
End;

(*
    This is called just on the way out of the wizard
    The app Uninstall registry entry already exists
*)
procedure DeinitializeSetup();
begin
  (*
  	Write the original value of Test Mode to the Registry
  	If this is the second step it must be '0'
  	Otherwise we don't care.
  *)
  //MsgBox('Inside DeinitializeSetup()' , mbInformation, MB_OK)
	  RegWriteOrigTestMode(OrigTestMode);

  (* Write directory locations to the registry *)
  RegWriteDllFolderLocation();

end;

(*
	Get the original value of Test Mode - call it on InitializeSetup()

	There are 4 cases:
	1. Check if this is Phase2. If it is then the original value was False.
	2. If this is not Phase2, this might be repetition of the first phase:
	   The RunOnce registry entry is set to /PH2=1 so the original value is False.
	3. This can be a new installation over an already installed vJoy:
	   check the value in the registry (inside the appropriate Uninstall key).
	4. If this value does not exist check the current test mode.

  Keep the value for use in the ssPostInstall step.
*)
function GetOrigTestMode(): Boolean;
var
	data: String;
	UninstKeyVjoy: String;
	Adata: AnsiString;

begin
	(* Case 1 *)
	if ExpandConstant('{param:'+Ph2Flag+'|0}') = '1' then
		begin	// Case 1
			Log('GetOrigTestMode(): Case 1');
			Result := false;
			exit;
		end;	// Case 1

	(* Case 2 *)
	if RegQueryStringValue(HKLM, RunOnceKey, RunOnceName, data) then
		begin // Case 1/2
			Log('GetOrigTestMode(): RunOnce String is: '+ data);
			if Pos(Ph2Param,data) > 0  then
			begin	// Found PH2
				Log('GetOrigTestMode(): "PH2" was found in RunOnce key');
				Result := false;
				exit;
			end		// Found PH2
		end;	// Case 1/2

	(* Case 3 *)
  UninstKeyVjoy := UninstKey + GetAppId('')  + '_is1';
  if RegQueryBinaryValue(HKEY_LOCAL_MACHINE, UninstKeyVjoy, ValOrig, Adata) then
  	begin // Case 3
  	if Adata = #1 then
  		Result := true
  	else
  		Result := false;
  		Log('GetOrigTestMode(): Found entry in '+ UninstKeyVjoy);
  	exit;
  	end;	// Case 3

  	(* Case 4 *)
		Log('GetOrigTestMode(): call IsTestMode()');
  	Result := IsTestMode;

end;

(*
	Called when starting uninstall

	Check if need to Revert Test Mode to OFF
*)
function InitializeUninstall(): Boolean;
var
	UninstKeyVjoy: String;
	Adata: AnsiString;

begin
  Result := true				// Default
  OrigTestMode := true; // Default
	UninstKeyVjoy := UninstKey + GetAppId('') + '_is1';

  if RegQueryBinaryValue(HKEY_LOCAL_MACHINE, UninstKeyVjoy, ValOrig, Adata) then
  	begin
  		Log('InitializeUninstall(): Found entry in '+ UninstKeyVjoy);
  		if Adata = #0 then
  			OrigTestMode := false;
  	end;
end;

(*
	Need restart if the user choses to reset Test Mode
*)
function UninstallNeedRestart(): Boolean;
var
	ResetTestMode: Integer;

begin
	Result := False; // Defaul

	if (OrigTestMode = false) and  IsTestMode then
	begin // Test Mode Changed
		ResetTestMode := MsgBox(TestModeChanged, mbConfirmation, MB_YESNO);
		if ResetTestMode = IDYES then
		begin	// Reset Test Mode
			SetTestModeOff();
			result := True;
		end;	// Reset Test Mode
	end;  // Test Mode Changed
end;

(*
  Get AppID from command line parameter ID (/ID=ABC)
  If this parameter is missing use AppGUID constant
*)
function GetAppId(Param: String): String;
begin
 Result := ExpandConstant('{param:'+AppIdFlag+'}');
  if Length(Result)=0 then
    Result :=  expandconstant('{#AppGUID}');;

end;

function DelayedRestart(): Boolean;
begin
	Result:= DldRestart;
end;

(*
			If delayed restart needed then change exit value
*)
function GetCustomSetupExitCode: Integer;
begin
	if DldRestart then Result := 8;
end;

(*
    Normalize Flag:
    Remove one leading flag-sign: Slash(/) or Minus(-) - If missing return empty string
    Convert to lower case
*)
function  NormalizeFlag (inFlag : String) : String;

begin
    Result :=  '';
// Check length
    if (Length(inFlag) <2) then exit;

// Remove the first character if it '/' or '-'
    Result :=  inFlag;
    Delete(Result, 1, 1)

// Convert to lower case
    Result := Lowercase(Result);

end;

(*
    Allows for standard command line parsing assuming a key/value organization
    Based on:  http://stackoverflow.com/questions/3618257/is-it-possible-to-accept-custom-command-line-parameters-with-innosetup
*)
function GetCommandlineParam (inParam: String):String;
var
  LoopVar : Integer;
  BreakLoop : Boolean;
  strParam : String;

begin
  { Init the variable to known values }
  LoopVar :=0;
  Result := '';
  BreakLoop := False;

  { Loop through the passed in arry to find the parameter }
  while ( (LoopVar < ParamCount) and (not BreakLoop) ) do
  begin

  strParam := NormalizeFlag(ParamStr(LoopVar));

    { Determine if the looked for parameter is the next value }
    if ( (strParam = inParam) and ( (LoopVar+1) <= ParamCount )) then
    begin
      { Set the return result equal to the next command line parameter }
      Result := ParamStr(LoopVar+1);

      { Break the loop }
      BreakLoop := True;
      Log('GetCommandlineParam(): Flag: '+ inParam + ' Value: ' + Result);
    end;

    { Increment the loop variable }
    LoopVar := LoopVar + 1;
  end;

  if (BreakLoop = False) then Log('GetCommandlineParam(): Flag: '+ inParam + ' not found');
end;

(*
    Gets from the command line the name of the file to merge into the registry
    If exists returns TRUE else FALSE
*)
function InitFromRegistry(): Boolean;
var
  FileName : String ;
  ResultCode: Integer;
begin
  Result := FALSE;

  // Gets the file name - exit with FALSE if fails
  FileName :=  GetCommandlineParam(ParamInitReg);
  if (Length(FileName) = 0 )   then exit;

  // Merge file to registry
  if (not FileExists(ExpandConstant('{src}\'+FileName))) then
    begin
      Log('InitFromRegistry(): File' + ExpandConstant('{src}\'+FileName) + ' not found');
      exit;
    end;

  if Exec(ExpandConstant('{win}\regedit.exe'), '/s ' + FileName, ExpandConstant('{src}'), SW_HIDE, ewWaitUntilTerminated, ResultCode) then   Result := TRUE;

  if (Result = TRUE) then
        Log('InitFromRegistry(): Merging file  ' + FileName + ' into the registry - code: ' + IntToStr(ResultCode))
  else
        Log('InitFromRegistry(): Merging file  ' + FileName + ' into the registry - Failed');

end;


Windows installer: added shortcuts to some mods including CrazyMod 8.2

#define FileHandle FileOpen("version.txt")
#define MyAppVer FileRead(FileHandle)

#define FileHandle FileOpen("version-name.txt")
#define MyAppVerName FileRead(FileHandle)

#define FileHandle FileOpen("stage.txt")
#define MyAppStage FileRead(FileHandle)

#define FileHandle FileOpen("stage-name.txt")
#define MyAppStageName FileRead(FileHandle)

#if MyAppStage == "stable"
#define MyAppStage
#define MyAppStageName
#endif

[Setup]
AppName=SoundRTS {#MyAppStageName}
AppVerName=SoundRTS {#MyAppVerName}
AppPublisher=SoundMud
AppPublisherURL=http://jlpo.free.fr/soundrts
AppSupportURL=http://jlpo.free.fr/soundrts
AppUpdatesURL=http://jlpo.free.fr/soundrts
DefaultDirName={pf}\SoundRTS {#MyAppStage}
DefaultGroupName=SoundRTS {#MyAppStageName}
Compression=lzma
SolidCompression=true
OutputBaseFilename=soundrts-{#MyAppVer}
OutputDir=..\dist
ShowLanguageDialog=auto
PrivilegesRequired=none

[Files]
Source: soundrts-{#MyAppVer}-windows\*; Excludes: \user; DestDir: {app}; Flags: ignoreversion recursesubdirs createallsubdirs

[Dirs]
Name: {userappdata}\SoundRTS {#MyAppStage}

[Icons]
Name: {group}\SoundRTS; Filename: {app}\soundrts.exe; WorkingDir: {app}
Name: {group}\mods\Sound pack; Filename: {app}\soundrts.exe; Parameters: --mods=soundpack; WorkingDir: {app}
Name: {group}\mods\CrazyMod 8.2 (if installed); Filename: {app}\soundrts.exe; Parameters: --mods=soundpack,CrazyMod8.2; WorkingDir: {app}
Name: {group}\mods\Orcs; Filename: {app}\soundrts.exe; Parameters: --mods=orc; WorkingDir: {app}
Name: {group}\mods\Teleportation; Filename: {app}\soundrts.exe; Parameters: --mods=teleportation; WorkingDir: {app}
Name: {group}\mods\Vanilla (no mod); Filename: {app}\soundrts.exe; Parameters: --mods=; WorkingDir: {app}
Name: {group}\Manual; Filename: {app}\doc\help-index.htm
Name: {group}\Web site; Filename: http://jlpo.free.fr/soundrts
Name: {group}\{cm:UninstallProgram, SoundRTS}; Filename: {uninstallexe}
Name: {group}\user; Filename: {userappdata}\SoundRTS {#MyAppStage}

[Languages]
Name: English; MessagesFile: compiler:Default.isl
Name: BrazilianPortuguese; MessagesFile: compiler:Languages\BrazilianPortuguese.isl
Name: Chinese; MessagesFile: ChineseSimp-12-5.1.11.isl
Name: Czech; MessagesFile: compiler:Languages\Czech.isl
Name: Dutch; MessagesFile: compiler:Languages\Dutch.isl
Name: French; MessagesFile: compiler:Languages\French.isl
Name: German; MessagesFile: compiler:Languages\German.isl
Name: Italian; MessagesFile: compiler:Languages\Italian.isl
Name: Polish; MessagesFile: compiler:Languages\Polish.isl
Name: Russian; MessagesFile: compiler:Languages\Russian.isl
Name: Slovak; MessagesFile: compiler:Languages\Slovak.isl
Name: Spanish; MessagesFile: compiler:Languages\Spanish.isl

[_ISTool]
UseAbsolutePaths=true

#define FileHandle FileOpen("version.txt")
#define MyAppVer FileRead(FileHandle)

#define FileHandle FileOpen("version-name.txt")
#define MyAppVerName FileRead(FileHandle)

#define FileHandle FileOpen("stage.txt")
#define MyAppStage FileRead(FileHandle)

#define FileHandle FileOpen("stage-name.txt")
#define MyAppStageName FileRead(FileHandle)

#if MyAppStage == "stable"
#define MyAppStage
#define MyAppStageName
#endif

[Setup]
AppName=SoundRTS {#MyAppStageName}
AppVerName=SoundRTS {#MyAppVerName}
AppPublisher=SoundMud
AppPublisherURL=http://jlpo.free.fr/soundrts
AppSupportURL=http://jlpo.free.fr/soundrts
AppUpdatesURL=http://jlpo.free.fr/soundrts
DefaultDirName={pf}\SoundRTS {#MyAppStage}
DefaultGroupName=SoundRTS {#MyAppStageName}
Compression=lzma
SolidCompression=true
OutputBaseFilename=soundrts-{#MyAppVer}
OutputDir=..\dist
ShowLanguageDialog=auto
PrivilegesRequired=none

[Files]
Source: soundrts-{#MyAppVer}-windows\*; Excludes: \user; DestDir: {app}; Flags: ignoreversion recursesubdirs createallsubdirs

[Dirs]
Name: {userappdata}\SoundRTS {#MyAppStage}

[Icons]
Name: {group}\SoundRTS; Filename: {app}\soundrts.exe; WorkingDir: {app}
Name: {group}\Manual; Filename: {app}\doc\help-index.htm
Name: {group}\Web site; Filename: http://jlpo.free.fr/soundrts
Name: {group}\{cm:UninstallProgram, SoundRTS}; Filename: {uninstallexe}
Name: {group}\user; Filename: {userappdata}\SoundRTS {#MyAppStage}

[Languages]
Name: English; MessagesFile: compiler:Default.isl
Name: BrazilianPortuguese; MessagesFile: compiler:Languages\BrazilianPortuguese.isl
Name: Chinese; MessagesFile: ChineseSimp-12-5.1.11.isl
Name: Czech; MessagesFile: compiler:Languages\Czech.isl
Name: Dutch; MessagesFile: compiler:Languages\Dutch.isl
Name: French; MessagesFile: compiler:Languages\French.isl
Name: German; MessagesFile: compiler:Languages\German.isl
Name: Italian; MessagesFile: compiler:Languages\Italian.isl
Name: Polish; MessagesFile: compiler:Languages\Polish.isl
Name: Russian; MessagesFile: compiler:Languages\Russian.isl
Name: Slovak; MessagesFile: compiler:Languages\Slovak.isl
Name: Spanish; MessagesFile: compiler:Languages\Spanish.isl

[_ISTool]
UseAbsolutePaths=true


Final installer tweaks for 0.2.1.

Final installer tweaks for 0.2.1.

; Copyright (c) 2009 SlimDX Group
;
; Permission is hereby granted, free of charge, to any person obtaining a copy
; of this software and associated documentation files (the "Software"), to deal
; in the Software without restriction, including without limitation the rights
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
; copies of the Software, and to permit persons to whom the Software is
; furnished to do so, subject to the following conditions:
;
; The above copyright notice and this permission notice shall be included in
; all copies or substantial portions of the Software.
;
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
; THE SOFTWARE.

[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={{72513408-FD69-404F-9FDB-2DB6A7DCDE84}
AppName=SlimTune Profiler
AppVerName=SlimTune Profiler v0.2.1
AppPublisher=SlimDX Group
AppPublisherURL=http://www.slimtune.com/
AppSupportURL=http://www.slimtune.com/
AppUpdatesURL=http://www.slimtune.com/
DefaultDirName={pf}\SlimTune Profiler
DefaultGroupName=SlimTune Profiler
LicenseFile=..\ExtraFiles\License.rtf
OutputDir=.
OutputBaseFilename=SlimTune-0.2.1
Compression=lzma
SolidCompression=yes
UsePreviousAppDir=yes
MinVersion=0,5.01
VersionInfoVersion=0.2.1.0
VersionInfoCompany=SlimDX Group
VersionInfoCopyright=Copyright  SlimDX Group 2010
VersionInfoProductName=SlimTune Profiler v0.2.1

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

[Files]
Source: "..\ExtraFiles\x86\vcredist_x86.exe"; DestDir: "{tmp}"; Flags: ignoreversion; AfterInstall: InstallVCRedist('x86')
Source: "..\ExtraFiles\x64\vcredist_x64.exe"; DestDir: "{tmp}"; Flags: ignoreversion; Check: IsWin64; AfterInstall: InstallVCRedist('x64')

Source: "..\publish\*"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\publish\Backends\x86\SlimTuneCLR.dll"; DestDir: "{app}\Backends\x86"; Flags: 32bit regserver ignoreversion
Source: "..\publish\Backends\x64\SlimTuneCLR.dll"; DestDir: "{app}\Backends\x64"; Check: IsWin64; Flags: 64bit regserver ignoreversion

Source: "..\publish\Backends\*"; DestDir: "{app}\Backends"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\publish\Plugins\*"; DestDir: "{app}\Plugins"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\publish\Api\*"; DestDir: "{app}\Api"; Flags: ignoreversion recursesubdirs createallsubdirs

Source: "..\ExtraFiles\x86\SSCERuntime-ENU-x86.msi"; DestDir: "{tmp}"; Flags: ignoreversion

[Registry]
Root: HKLM; Subkey: "Software\SlimDX Group"; Flags: uninsdeletekeyifempty
Root: HKLM; Subkey: "Software\SlimDX Group\SlimTune"; Flags: uninsdeletekey
Root: HKLM; Subkey: "Software\SlimDX Group\SlimTune"; ValueType: string; ValueName: "InstallPath"; ValueData: "{app}"
Root: HKLM; Subkey: "Software\SlimDX Group\SlimTune"; ValueType: string; ValueName: "PluginsPath"; ValueData: "{app}\Plugins"

[Icons]
Name: "{group}\SlimTune Profiler"; Filename: "{app}\SlimTuneUI.exe"
Name: "{group}\SlimTune Help"; Filename: "{app}\SlimTune.chm"
Name: "{group}\{cm:UninstallProgram,SlimTune Profiler}"; Filename: "{uninstallexe}"

[Tasks]
Name: Firewall; Description: "Open TCP subnet ports 3000 - 3001 in Windows Firewall"; GroupDescription: "Firewall:"; MinVersion: 0,5.01.2600sp2;

[Run]
Filename: "msiexec.exe"; Parameters: "/passive /i ""{tmp}\SSCERuntime-ENU-x86.msi"""; StatusMsg: "Installing SQL Server Compact Edition"
Filename: "{sys}\netsh.exe"; Parameters: "firewall add portopening TCP 3000 ""SlimTune Profiler (3000)"" ENABLE SUBNET"; Flags: runhidden; Tasks: Firewall;
Filename: "{sys}\netsh.exe"; Parameters: "firewall add portopening TCP 3001 ""SlimTune Profiler (3001)"" ENABLE SUBNET"; Flags: runhidden; Tasks: Firewall;

Filename: "{app}\SlimTuneUI.exe"; Description: "{cm:LaunchProgram,SlimTune Profiler}"; Flags: nowait postinstall skipifsilent

[UninstallRun]
Filename: "{sys}\netsh.exe"; Parameters: "firewall delete portopening TCP 3000"; Flags: runhidden; MinVersion:0,5.01.2600sp2; Tasks: Firewall;
Filename: "{sys}\netsh.exe"; Parameters: "firewall delete portopening TCP 3001"; Flags: runhidden; MinVersion:0,5.01.2600sp2; Tasks: Firewall;

[Code]
function IsX64: Boolean;
begin
  Result := IsWin64 and (ProcessorArchitecture = paX64);
end;

function InitializeSetup(): Boolean;
var
  NetFrameWorkInstalled : Boolean;
begin
  NetFrameWorkInstalled := RegKeyExists(HKLM,'SOFTWARE\Microsoft\.NETFramework\policy\v2.0');
  if NetFrameWorkInstalled then
  begin
    Result := true;
  end else
  begin
    MsgBox('This setup requires the .NET Framework 2.0 or later. Please download and install the .NET Framework and run this setup again.',
      mbConfirmation, MB_OK);
    Result:=false;
  end;
end;

procedure InstallVCRedist(arch: String);
var
  TempDir:      String;
  RedistPath:   String;
  ReturnCode:   Integer;
begin
  TempDir := ExpandConstant('{tmp}');
  RedistPath := TempDir + '\vcredist_' + arch + '.exe';

  Exec(RedistPath, '/qb!', TempDir, SW_SHOW, ewWaitUntilTerminated, ReturnCode)
end;

; Copyright (c) 2009 SlimDX Group
;
; Permission is hereby granted, free of charge, to any person obtaining a copy
; of this software and associated documentation files (the "Software"), to deal
; in the Software without restriction, including without limitation the rights
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
; copies of the Software, and to permit persons to whom the Software is
; furnished to do so, subject to the following conditions:
;
; The above copyright notice and this permission notice shall be included in
; all copies or substantial portions of the Software.
;
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
; THE SOFTWARE.

[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={72513408-FD69-404F-9FDB-2DB6A7DCDE84}
AppName=SlimTune Profiler
AppVerName=SlimTune Profiler v0.2.1
AppPublisher=SlimDX Group
AppPublisherURL=http://www.slimtune.com/
AppSupportURL=http://www.slimtune.com/
AppUpdatesURL=http://www.slimtune.com/
DefaultDirName={pf}\SlimTune Profiler
DefaultGroupName=SlimTune Profiler
LicenseFile=..\ExtraFiles\License.rtf
OutputDir=.
OutputBaseFilename=SlimTune-0.2.1
Compression=lzma
SolidCompression=yes
UsePreviousAppDir=yes
MinVersion=0,5.01
VersionInfoVersion=0.2.1.0
VersionInfoCompany=SlimDX Group
VersionInfoCopyright=Copyright  SlimDX Group 2010
VersionInfoProductName=SlimTune Profiler v0.2.1

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

[Files]
Source: "..\ExtraFiles\x86\vcredist_x86.exe"; DestDir: "{tmp}"; Flags: ignoreversion; AfterInstall: InstallVCRedist('x86')
Source: "..\ExtraFiles\x64\vcredist_x64.exe"; DestDir: "{tmp}"; Flags: ignoreversion; Check: IsWin64; AfterInstall: InstallVCRedist('x64')

Source: "..\publish\*"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\publish\Backends\x86\SlimTuneCLR.dll"; DestDir: "{app}\Backends\x86"; Flags: 32bit regserver ignoreversion
Source: "..\publish\Backends\x64\SlimTuneCLR.dll"; DestDir: "{app}\Backends\x64"; Check: IsWin64; Flags: 64bit regserver ignoreversion

Source: "..\publish\Backends\*"; DestDir: "{app}\Backends"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\publish\Plugins\*"; DestDir: "{app}\Plugins"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\publish\Api\*"; DestDir: "{app}\Api"; Flags: ignoreversion recursesubdirs createallsubdirs

Source: "..\ExtraFiles\x86\SSCERuntime-ENU-x86.msi"; DestDir: "{tmp}"; Flags: ignoreversion

[Registry]
Root: HKLM; Subkey: "Software\SlimDX Group"; Flags: uninsdeletekeyifempty
Root: HKLM; Subkey: "Software\SlimDX Group\SlimTune"; Flags: uninsdeletekey
Root: HKLM; Subkey: "Software\SlimDX Group\SlimTune"; ValueType: string; ValueName: "InstallPath"; ValueData: "{app}"
Root: HKLM; Subkey: "Software\SlimDX Group\SlimTune"; ValueType: string; ValueName: "PluginsPath"; ValueData: "{app}\Plugins"

[Icons]
Name: "{group}\SlimTune Profiler"; Filename: "{app}\SlimTuneUI.exe"
Name: "{group}\{cm:UninstallProgram,SlimTune Profiler}"; Filename: "{uninstallexe}"

[Tasks]
Name: Firewall; Description: "Open TCP subnet ports 3000 - 3001 in Windows Firewall"; GroupDescription: "Firewall:"; MinVersion: 0,5.01.2600sp2;

[Run]
Filename: "msiexec.exe"; Parameters: "/passive /i ""{tmp}\SSCERuntime-ENU-x86.msi"""; StatusMsg: "Installing SQL Server Compact Edition"
Filename: "{sys}\netsh.exe"; Parameters: "firewall add portopening TCP 3000 ""SlimTune Profiler (3000)"" ENABLE SUBNET"; Flags: runhidden; Tasks: Firewall;
Filename: "{sys}\netsh.exe"; Parameters: "firewall add portopening TCP 3001 ""SlimTune Profiler (3001)"" ENABLE SUBNET"; Flags: runhidden; Tasks: Firewall;

Filename: "{app}\SlimTuneUI.exe"; Description: "{cm:LaunchProgram,SlimTune Profiler}"; Flags: nowait postinstall skipifsilent

[UninstallRun]
Filename: "{sys}\netsh.exe"; Parameters: "firewall delete portopening TCP 3000"; Flags: runhidden; MinVersion:0,5.01.2600sp2; Tasks: Firewall;
Filename: "{sys}\netsh.exe"; Parameters: "firewall delete portopening TCP 3001"; Flags: runhidden; MinVersion:0,5.01.2600sp2; Tasks: Firewall;

[Code]
function IsX64: Boolean;
begin
  Result := IsWin64 and (ProcessorArchitecture = paX64);
end;

function InitializeSetup(): Boolean;
var
  NetFrameWorkInstalled : Boolean;
begin
  NetFrameWorkInstalled := RegKeyExists(HKLM,'SOFTWARE\Microsoft\.NETFramework\policy\v2.0');
  if NetFrameWorkInstalled then
  begin
    Result := true;
  end else
  begin
    MsgBox('This setup requires the .NET Framework 2.0 or later. Please download and install the .NET Framework and run this setup again.',
      mbConfirmation, MB_OK);
    Result:=false;
  end;
end;

procedure InstallVCRedist(arch: String);
var
  TempDir:      String;
  RedistPath:   String;
  ReturnCode:   Integer;
begin
  TempDir := ExpandConstant('{tmp}');
  RedistPath := TempDir + '\vcredist_' + arch + '.exe';

  Exec(RedistPath, '/qb!', TempDir, SW_SHOW, ewWaitUntilTerminated, ReturnCode)
end;


Remove code that is asking for administrative rights (I hope).

; -- xins.iss --
;
; $Id$

[Setup]
AppName=XINS
AppVerName=XINS version %%VERSION%%
DefaultDirName={pf}\xins
VersionInfoVersion=%%VERSION%%
OutputDir=C:\projects
OutputBaseFilename=xins-%%VERSION%%
SetupIconFile=xins.ico
WizardImageFile=bigxinslogo.bmp
WizardSmallImageFile=smallxinslogo.bmp
UninstallDisplayIcon={app}\xins.ico
DefaultGroupName=XINS
DisableProgramGroupPage=yes
LicenseFile=C:\projects\xins-%%VERSION%%\COPYRIGHT
InfoBeforeFile=xins-info1.txt

[Files]
Source: "C:\projects\xins-%%VERSION%%\*"; DestDir: "{app}"; Flags: recursesubdirs
Source: "xins.ico"; DestDir: "{app}"

[Icons]
Name: "{group}\Run demo"; Filename: "{app}\demo\rundemo.bat"; WorkingDir: "{app}\demo\"; IconFilename: "{app}\xins.ico"
Name: "{group}\Readme"; Filename: "{app}\README.html"; WorkingDir: "{app}"
Name: "{group}\Guideline"; Filename: "{app}\docs\index.html"; WorkingDir: "{app}"
Name: "{group}\Primer"; Filename: "{app}\docs\primer\primer.html"; WorkingDir: "{app}"
;Name: "{group}\{cm:UninstallProgram,XINS}"; Filename: "{uninstallexe}"

[Registry]
Root: HKCU; Subkey: "Environment"; ValueType: string; ValueName: "XINS_HOME"; ValueData: "{app}"; Flags: uninsdeletevalue
Root: HKCU; Subkey: "Environment"; ValueType: expandsz; ValueName: "PATH"; ValueData: "{code:GetNewPath|{app}\bin}"; Flags: preservestringtype
;"{app}\bin;{reg:HKCU\Environment,PATH|""}"; Flags: preservestringtype

[Run]
Filename: "{app}\README.html"; Description: "View the README file."; Flags: postinstall nowait shellexec skipifsilent
Filename: "{app}\demo\rundemo.bat"; WorkingDir: "{app}\demo"; Description: "Compile and run demo."; Flags: postinstall nowait skipifsilent unchecked
;Filename: "set XINS_HOME={app};{app}\bin\xins.bat download-tools"; WorkingDir: "{app}\demo\xins-project"; Description: "Download optional tools libraries."; Flags: postinstall nowait skipifsilent unchecked

[UninstallDelete]
Type: filesandordirs; Name: "{app}\demo\xins-project\build\*"
Type: dirifempty; Name: "{app}\demo\xins-project\build"
Type: dirifempty; Name: "{app}\demo\xins-project"
Type: dirifempty; Name: "{app}\demo"
Type: dirifempty; Name: "{app}"

[Code]
var
  CurrentPath: String;
  UsersPath: String;

function ShouldSkipPage(PageID: Integer): Boolean;
begin
  { Do no show the InfoBeforeFile page if the environment variables are correct. }
  if (PageID = wpInfoBefore) and (not (GetEnv('ANT_HOME') = '')) and (not (GetEnv('JAVA_HOME') = '')) then begin
    Result := True;
  end else begin
    Result := False;
  end;
end;

function GetNewPath(XPath: String): String;
begin
  CurrentPath := ExpandConstant('{reg:HKCU\Environment,PATH}');
  { UsersPath := ExpandConstant('{reg:HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment,PATH}'); }
  if (Length(CurrentPath) = 0) then begin
    Result := XPath;
  { end else if ((Pos(XPath, CurrentPath) = 0) and (Pos(XPath, UsersPath) = 0)) then begin
    Result := XPath + ';' + CurrentPath; }
  end else begin
    Result := CurrentPath;
  end;
end;

; -- xins.iss --
;
; $Id$

[Setup]
AppName=XINS
AppVerName=XINS version %%VERSION%%
DefaultDirName={pf}\xins
VersionInfoVersion=%%VERSION%%
OutputDir=C:\projects
OutputBaseFilename=xins-%%VERSION%%
SetupIconFile=xins.ico
WizardImageFile=bigxinslogo.bmp
WizardSmallImageFile=smallxinslogo.bmp
UninstallDisplayIcon={app}\xins.ico
DefaultGroupName=XINS
DisableProgramGroupPage=yes
LicenseFile=C:\projects\xins-%%VERSION%%\COPYRIGHT
InfoBeforeFile=xins-info1.txt

[Files]
Source: "C:\projects\xins-%%VERSION%%\*"; DestDir: "{app}"; Flags: recursesubdirs
Source: "xins.ico"; DestDir: "{app}"

[Icons]
Name: "{group}\Run demo"; Filename: "{app}\demo\rundemo.bat"; WorkingDir: "{app}\demo\"; IconFilename: "{app}\xins.ico"
Name: "{group}\Readme"; Filename: "{app}\README.html"; WorkingDir: "{app}"
Name: "{group}\Guideline"; Filename: "{app}\docs\index.html"; WorkingDir: "{app}"
Name: "{group}\Primer"; Filename: "{app}\docs\primer\primer.html"; WorkingDir: "{app}"
;Name: "{group}\{cm:UninstallProgram,XINS}"; Filename: "{uninstallexe}"

[Registry]
Root: HKCU; Subkey: "Environment"; ValueType: string; ValueName: "XINS_HOME"; ValueData: "{app}"; Flags: uninsdeletevalue
Root: HKCU; Subkey: "Environment"; ValueType: expandsz; ValueName: "PATH"; ValueData: "{code:GetNewPath|{app}\bin}"; Flags: preservestringtype
;"{app}\bin;{reg:HKCU\Environment,PATH|""}"; Flags: preservestringtype

[Run]
Filename: "{app}\README.html"; Description: "View the README file."; Flags: postinstall nowait shellexec skipifsilent
Filename: "{app}\demo\rundemo.bat"; WorkingDir: "{app}\demo"; Description: "Compile and run demo."; Flags: postinstall nowait skipifsilent unchecked
;Filename: "set XINS_HOME={app};{app}\bin\xins.bat download-tools"; WorkingDir: "{app}\demo\xins-project"; Description: "Download optional tools libraries."; Flags: postinstall nowait skipifsilent unchecked

[UninstallDelete]
Type: filesandordirs; Name: "{app}\demo\xins-project\build\*"
Type: dirifempty; Name: "{app}\demo\xins-project\build"
Type: dirifempty; Name: "{app}\demo\xins-project"
Type: dirifempty; Name: "{app}\demo"
Type: dirifempty; Name: "{app}"

[Code]
var
  CurrentPath: String;
  UsersPath: String;

function ShouldSkipPage(PageID: Integer): Boolean;
begin
  { Do no show the InfoBeforeFile page if the environment variables are correct. }
  if (PageID = wpInfoBefore) and (not (GetEnv('ANT_HOME') = '')) and (not (GetEnv('JAVA_HOME') = '')) then begin
    Result := True;
  end else begin
    Result := False;
  end;
end;

function GetNewPath(XPath: String): String;
begin
  CurrentPath := ExpandConstant('{reg:HKCU\Environment,PATH}');
  UsersPath := ExpandConstant('{reg:HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment,PATH}');
  if (Length(CurrentPath) = 0) then begin
    Result := XPath;
  end else if ((Pos(XPath, CurrentPath) = 0) and (Pos(XPath, UsersPath) = 0)) then begin
    Result := XPath + ';' + CurrentPath;
  end else begin
    Result := CurrentPath;
  end;
end;