;!verbose 3

!ifndef PACKAGE
	!define PACKAGE ..\..
!endif

!macro !echo msg
	!verbose push
	!verbose 4
	!echo "${msg}"
	!verbose pop
!macroend
!define !echo "!insertmacro !echo"

;=== Require at least Unicode NSIS 2.46 {{{1
!include RequireLatestNSIS.nsh
!define NewLine `$\r$\n`

### PRIVILEGES ###
!define ExecAsUser          ;=== for apps. which need to run as normal user.
;!define Include_StdUtils.nsh ;=== include StndUtils w/out ExecAsUser
!define RequestLevel USER
!define ResHacker    `${NSISDIR}\Contrib\Manifests\ResHacker.exe`
!define ManifDir     `${NSISDIR}\Contrib\Manifests`
!define Manifest     `NSIS_2.46_Win8`
!packhdr             `$%TEMP%\exehead.tmp` `"${Reshacker}" -addoverwrite "%TEMP%\exehead.tmp", "%TEMP%\exehead.tmp", "${ManifDir}\${Manifest}_${RequestLevel}.manifest", 24,1,1033`

;=== Custom Defines
;!define Sleep1000           ;=== Sleep for Execute
;!define Sleep2000           ;=== Sleep for Execute
!define Sleep50              ;=== Sleep value for RegistryValueWrite. else function is innaccurate.
;!define NETCheck             ;=== function to check for .NET Framework.
;!define SetSysWOW64         ;=== Sets $SysWOW64 variable.
;!define SetAllUsersAppData  ;=== Sets $ALLUSERSAPPDATA variable.
!define CloseProc
;!define DisablePAL:LanguageCustom
;!define DisableProgramExecSegment ;=== for apps. w/UAC & ExecAsAdmin (prevents secondary UAC Prompt)
!define SYSTEMWIDE_DISABLEREDIR
!define FORCE_SYSTEMWIDE_DISABLEREDIR ;=== for both x86 and x64.
;!define RMEMPTYDIRECTORIES
;!define JAVA
!define UAC
;!define XML_PLUGIN
!define REGISTERDLL
!define REPLACE
;!define TLB_FUNCTION
;!define FIREWALL
;!define NSIS_REGISTRY
!define 64.nsh
;!include StrRep.nsh
;!include RIF.nsh
;!define Disable_Settings
!define REGISTRY
!define SERVICES
;!define DirectoriesMoveVista ;=== for Vista + only. ie. LocalAppDataLow
;!define DIRECTORIES_MOVE
!define FILES_MOVE
;!define X64_DIR_ENABLED ; this separates x64 dir & registry functions.
;!define FONTS_ENABLE
;!define LocalLow
;!define PublicDoc
;!define NTFS
;!define ACL
;!define ACL_DIR
!define CloseWindow
;!define DisableRMDirPostDirMove ; enable for SRWareIron
;!define SSDL
;!define GetBetween.nsh
;!define GetLocale.nsh
;!include Find.nsh
;!define WININET_FUNCTION
;!define TrimString
!define IsFileLocked ;=== enable ${If} ${FileLocked} / ${IfNot} ${FileLocked}

# INCLUDES
;!include LineWrite.nsh
!include WinMessages.nsh

!ifdef SetAllUsersAppData
	!define AllUsersAppData
!endif
!ifdef JAVA
	Var UsingJavaExecutable
	Var JavaMode
	Var JavaDirectory
!endif
!ifdef UAC
	Var RunAsAdmin
	!include UAC.nsh
	!ifndef TrimString
		!define TrimString
	!endif
!endif
!ifdef REGISTRY
	!include Registry.nsh
	!define REGEXE `$SYSDIR\reg.exe`
	!define REGEDIT `$SYSDIR\regedit.exe`
;	!define DISABLEFSR               ;=== requires ${APP64}
	!define RegistryKeys_x86         ;=== redirected for ${APP64}, else disabled for ${APP} and ${If} ${RunningX64}
	!define RegistryValueBackupDelete86
;	!define RegistryCleanup86
;	!define RegistryKeys_WOW6432Node ;=== x64 only | x32 keys.
;	!define RegistryKeys32Only
;	!define RegistryKeys64
;		!define Test_APP ;=== Test for APP vs. ${RunningX64}
;	!define RegistryKeys64Only
;	!define RegistryKeys64Only_DisableFSR
;	!define RegistryCopyKeys64
;	!define RegistryValueDelete64
;	!define RegistryValueBackupDelete64
;	!define RegistryValueWrite64     ;=== disable redir for x64.
;	!define RegistryCleanup64
;	!define RegistryKeys_Win8
;	!define RegistryValueWrite32only
;	!define RegistryValueWrite64only
	!define RegistryValueBackupDelete32 ;=== for x32-bit keys regardless of architecture.
	#### REGISTRYVALUEWRITE ###
;	!define WRITEREGBIN
!endif

### APPLICATION SPECIFICATIONS ###
!define APP             PowerISO
!define APPNAME         `${APP}Portable`
!define FULLNAME        PowerISO
!define PORTABLEAPPNAME `${FULLNAME} Portable`
!define APPDIR          `$EXEDIR\App\${APP}`
!define APPINFO         `$EXEDIR\App\AppInfo`
!define DATA            `$EXEDIR\Data`
!define SET             `${DATA}\settings`
!define DEFDATA         `$EXEDIR\App\DefaultData`
!define DEFSET          `${DEFDATA}\settings`
!define LAUNCHDIR       `${APPINFO}\Launcher`
!define LAUNCHER        `${LAUNCHDIR}\${APPNAME}.ini`
!define LAUNCHER2       `$PLUGINSDIR\launcher.ini`
!define RUNTIME         `${DATA}\PortableApps.comLauncherRuntimeData-${APPNAME}.ini`
!define RUNTIME2        `$PLUGINSDIR\runtimedata.ini`
!define SETINI          `${SET}\${APPNAME}Settings.ini`
!define CONFIG          `$EXEDIR\${APPNAME}.ini`
!define OTHER           `$EXEDIR\Other`

;=== Runtime Switches {{{1
WindowIcon Off
XPStyle on
SilentInstall Silent
AutoCloseWindow True
!ifdef RUNASADMIN_COMPILEFORCE
	RequestExecutionLevel admin
!else
	RequestExecutionLevel user
!endif
SetCompressor /SOLID lzma
SetCompressorDictSize 32

;=== MACROS
!define PAL          PortableApps.comLauncher
!define LCID         `kernel32::GetUserDefaultLangID()i .r0`
!define GETSYSWOW64  `kernel32::GetSystemWow64Directory(t .r0, i ${NSIS_MAX_STRLEN})`
!define DISABLEREDIR `kernel32::Wow64EnableWow64FsRedirection(i0)`
!define ENABLEREDIR  `kernel32::Wow64EnableWow64FsRedirection(i1)`
!define GETCURRPROC  `kernel32::GetCurrentProcess()i.s`
!define WOW          `kernel32::IsWow64Process(is,*i.r0)`
Function IsWOW64
	!macro _IsWOW64 _RETURN
		Push ${_RETURN}
		Call IsWOW64
		Pop ${_RETURN}
	!macroend
	!define IsWOW64 `!insertmacro _IsWOW64`
	Exch $0
	System::Call `${GETCURRPROC}`
	System::Call `${WOW}`
	Exch $0 ; 0 = 32
FunctionEnd
!define ReadLauncherConfig `!insertmacro ReadLauncherConfig`
!macro ReadLauncherConfig _RETURN _SECTION _ENTRY
	ReadINIStr ${_RETURN} `${LAUNCHER}` `${_SECTION}` `${_ENTRY}`
!macroend
!define WriteLauncherConfig `!insertmacro WriteLauncherConfig`
!macro WriteLauncherConfig _SECTION _ENTRY _VALUE
	WriteINIStr `${LAUNCHER}` `${_SECTION}` `${_ENTRY}` `${_VALUE}`
!macroend
!define DeleteLauncherConfig `!insertmacro DeleteLauncherConfig`
!macro DeleteLauncherConfig _SECTION _ENTRY
	DeleteINIStr `${LAUNCHER}` `${_SECTION}` `${_ENTRY}`
!macroend
!define DeleteLauncherConfigSec `!insertmacro DeleteLauncherConfigSec`
!macro DeleteLauncherConfigSec _SECTION
	DeleteINISec `${LAUNCHER}` `${_SECTION}`
!macroend
!define ReadLauncherConfigWithDefault `!insertmacro ReadLauncherConfigWithDefault`
!macro ReadLauncherConfigWithDefault _RETURN _SECTION _VALUE _DEFAULT
	ClearErrors
	${ReadLauncherConfig} ${_RETURN} `${_SECTION}` `${_VALUE}`
	${IfThen} ${Errors} ${|} StrCpy ${_OUTPUT} `${_DEFAULT}` ${|}
!macroend
!define ReadUserConfig `!insertmacro ReadUserConfig`
!macro ReadUserConfig _RETURN _KEY
	${ConfigReadS} `${CONFIG}` `${_KEY}=` `${_RETURN}`
!macroend
!define WriteUserConfig `!insertmacro WriteUserConfig`
!macro WriteUserConfig _VALUE _KEY
	${ConfigWriteS} `${CONFIG}` `${_KEY}=` `${_VALUE}` $R0
!macroend
!define ReadUserOverrideConfig `!insertmacro ReadUserOverrideConfigError`
!macro ReadUserOverrideConfigError a b
	!error `ReadUserOverrideConfig has been renamed to ReadUserConfig in PAL 2.1.`
!macroend
!define InvalidValueError `!insertmacro InvalidValueError`
!macro InvalidValueError _SECTION_KEY _VALUE
	MessageBox MB_OK|MB_ICONSTOP `Error: invalid value '${_VALUE}' for ${_SECTION_KEY}. Please refer to the Manual for valid values.`
!macroend
!define WriteRuntimeData "!insertmacro WriteRuntimeData"
!macro WriteRuntimeData _SECTION _KEY _VALUE
	WriteINIStr `${RUNTIME}` `${_SECTION}` `${_KEY}` `${_VALUE}`
	WriteINIStr `${RUNTIME2}` `${_SECTION}` `${_KEY}` `${_VALUE}`
!macroend
!define DeleteRuntimeData "!insertmacro DeleteRuntimeData"
!macro DeleteRuntimeData _SECTION _KEY
	DeleteINIStr `${RUNTIME}` `${_SECTION}` `${_KEY}`
	DeleteINIStr `${RUNTIME2}` `${_SECTION}` `${_KEY}`
!macroend
!define ReadRuntimeData "!insertmacro ReadRuntimeData"
!macro ReadRuntimeData _RETURN _SECTION _KEY
	IfFileExists `${RUNTIME}` 0 +3
	ReadINIStr `${_RETURN}` `${RUNTIME}` `${_SECTION}` `${_KEY}`
	Goto +2
	ReadINIStr `${_RETURN}` `${RUNTIME2}` `${_SECTION}` `${_KEY}`
!macroend
!define WriteRuntime "!insertmacro WriteRuntime"
!macro WriteRuntime _VALUE _KEY
	WriteINIStr `${RUNTIME}` PortableApps.comLauncher `${_KEY}` `${_VALUE}`
	WriteINIStr `${RUNTIME2}` PortableApps.comLauncher `${_KEY}` `${_VALUE}`
!macroend
!define ReadRuntime "!insertmacro ReadRuntime"
!macro ReadRuntime _RETURN _KEY
	IfFileExists `${RUNTIME}` 0 +3
	ReadINIStr `${_RETURN}` `${RUNTIME}` PortableApps.comLauncher `${_KEY}`
	Goto +2
	ReadINIStr `${_RETURN}` `${RUNTIME2}` PortableApps.comLauncher `${_KEY}`
!macroend
!define WriteSettings `!insertmacro WriteSettings`
!macro WriteSettings _VALUE _KEY
	WriteINIStr `${SETINI}` ${APPNAME}Settings `${_KEY}` `${_VALUE}`
!macroend
!define ReadSettings `!insertmacro ReadSettings`
!macro ReadSettings _RETURN _KEY
	ReadINIStr `${_RETURN}` `${SETINI}` ${APPNAME}Settings `${_KEY}`
!macroend
!define DeleteSettings `!insertmacro DeleteSettings`
!macro DeleteSettings _KEY
	DeleteINIStr `${SETINI}` ${APPNAME}Settings `${_KEY}`
!macroend

;=== Include {{{1
!include LangFile.nsh
!include LogicLib.nsh
!include FileFunc.nsh
!include TextFunc.nsh
!include WordFunc.nsh
!ifdef UAC
	!include UAC.nsh
!endif

# CUSTOM
;!include servicelib.nsh
;!include Junction.nsh

;(NSIS Plugins) {{{2
### PLUGINS DIR ###
!ifdef TLB_FUNCTION
	!ifndef PLUGINSDIR
		!define PLUGINSDIR
		!addplugindir Plugins
	!endif
!endif
!ifdef ExecAsUser
	!include StdUtils.nsh
	!ifndef PLUGINSDIR
		!define PLUGINSDIR
		!addplugindir Plugins
	!endif
!endif
!ifdef REPLACE
	!include NewTextReplace.nsh
	!ifndef PLUGINSDIR
		!define PLUGINSDIR
		!addplugindir Plugins
	!endif
!endif
!ifdef FIREWALL
	!ifndef PLUGINSDIR
		!define PLUGINSDIR
		!addplugindir Plugins
	!endif
!endif
!ifdef UAC
	!ifndef PLUGINSDIR
		!define PLUGINSDIR
		!addplugindir Plugins
	!endif
!endif
!ifdef WRITEREGBIN
	!ifndef PLUGINSDIR
		!define PLUGINSDIR
		!addplugindir Plugins
	!endif
!endif
!ifdef XML_PLUGIN
	!include XML.nsh
	!ifndef PLUGINSDIR
		!define PLUGINSDIR
		!addplugindir Plugins
	!endif
!endif
!ifdef Include_StdUtils.nsh
	!ifndef ExecAsUser
		!include StdUtils.nsh
		!ifndef PLUGINSDIR
			!define PLUGINSDIR
			!addplugindir Plugins
		!endif
	!endif
!endif

!ifdef NSIS_REGISTRY
	!include NSISRegistry.nsh
	!insertmacro MOVEREGKEY
!endif

;(Custom) {{{2
!ifdef REPLACE
	!include ReplaceInFileWithTextReplace.nsh
!endif
!include ForEachINIPair.nsh
!include ForEachPath.nsh
!include SetFileAttributesDirectoryNormal.nsh
!include ProcFunc.nsh
!include EmptyWorkingSet.nsh
!include SetEnvironmentVariable.nsh
!include LogicLibAdditions.nsh
!ifdef GetBetween.nsh
	!include GetBetween.nsh
!endif
!ifdef GetLocale.nsh
	!include GetLocale.nsh
!endif
!ifdef 64.nsh
	!include x64.nsh
!endif
!ifdef IsFileLocked
	!ifndef 64.nsh
		!include x64.nsh
	!endif
!endif

;=== Languages {{{1
${!echo} "Loading language strings..."
!include Languages.nsh

;=== Variables {{{1
${!echo} "Initialising variables and macros..."
Var AppID
Var BaseName
Var MissingFileOrPath
Var AppName
Var AppNamePortable
Var ProgramExecutable
Var StatusMutex
Var WaitForProgram

; Load the segments {{{1
${!echo} "Loading segments..."
!include Segments.nsh

;=== Debugging {{{1
;!include Debug.nsh

### BRANDING ###
!define BUILD                    0.0.0.0
${!echo}                         `Specifying program details and setting options...`
Name                             `${PORTABLEAPPNAME}`
OutFile                          `${PACKAGE}\${APPNAME}.exe`
Icon                             `${PACKAGE}\App\AppInfo\appicon.ico`
Caption                          `${FULLNAME}`
VIProductVersion                 ${BUILD}
VIAddVersionKey ProductName      `${FULLNAME}`
VIAddVersionKey Comments         http://portablewares.blogspot.com/
VIAddVersionKey CompanyName      `Power Software Ltd`
VIAddVersionKey LegalCopyright   `Copyright (C) 2004-2015`
VIAddVersionKey FileDescription  `${FULLNAME}`
VIAddVersionKey FileVersion      ${BUILD}
VIAddVersionKey ProductVersion   Portable
VIAddVersionKey InternalName     `${APPNAME}.exe`
;VIAddVersionKey LegalTrademarks  
VIAddVersionKey OriginalFilename `${APPNAME}.exe`

!verbose 4

Function .onInit
	Push $0
	CreateDirectory `${SET}`
	!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
		!ifndef SYSTEMWIDE_DISABLEREDIR
			!define SYSTEMWIDE_DISABLEREDIR
		!endif
	!endif

	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!endif
	!endif

	${If} $SecondaryLaunch != true
		${RunSegment} Core
		${RunSegment} Custom
	${EndIf}

	${If} $SecondaryLaunch != true
		${RunSegment} Temp
		${RunSegment} Language
		${RunSegment} OperatingSystem
		!ifdef UAC
			${RunSegment} RunAsAdmin
		!endif
	${EndIf}

	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!endif
	!endif
	Pop $0
FunctionEnd

Function Init
	Push $0
	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!endif
	!endif

	${If} $SecondaryLaunch != true
		${RunSegment} Language
		${RunSegment} Environment
		${RunSegment} Custom
	${EndIf}

	${RunSegment} Core

	${If} $SecondaryLaunch != true
		${RunSegment} PathChecks
		${RunSegment} DriveLetter
		${RunSegment} DirectoryMoving
		${RunSegment} Variables
		!ifdef JAVA
			${RunSegment} Java
		!endif
		${RunSegment} RunLocally
		${RunSegment} Temp
	${EndIf}

	${RunSegment} InstanceManagement

	${If} $SecondaryLaunch != true
		${RunSegment} Settings
	${EndIf}

	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!endif
	!endif
	Pop $0
FunctionEnd

Function Pre
	Push $0
	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!endif
	!endif

	${If} $SecondaryLaunch != true
		!ifdef SERVICES
			${RunSegment} Services
		!endif
		!ifdef REGISTERDLL
			${RunSegment} RegisterDLL
		!endif
	${EndIf}

	!ifdef REGISTRY
		${RunSegment} Registry
	!endif
	${RunSegment} Custom
	${RunSegment} RunLocally
	${RunSegment} Temp
	${RunSegment} Environment
	${RunSegment} ExecString

	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!endif
	!endif
	Pop $0
FunctionEnd

Function PrePrimary
	Push $0
	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!endif
	!endif

	${If} $SecondaryLaunch != true
		${RunSegment} FilesBackup
		${RunSegment} FilesCleanup
	${EndIf}

	${RunSegment} Custom
	${RunSegment} DriveLetter
	${RunSegment} Variables
	${RunSegment} DirectoryMoving
	${RunSegment} FileWrite
	${RunSegment} FilesMove
	${RunSegment} DirectoriesMove
	!ifdef REGISTRY
		${RunSegment} RegistryKeys
		${If} $SecondaryLaunch != true
			${RunSegment} RegistryCopyKeys
		${EndIf}
		${RunSegment} RegistryValueBackupDelete
	!endif

	${If} $SecondaryLaunch != true
		!ifdef REGISTERDLL
			${RunSegment} RegisterDLL
		!endif
	${EndIf}

	!ifdef REGISTRY
		;=== this belongs here after Registering DLLs.
		${RunSegment} RegistryValueWrite
	!endif

	${If} $SecondaryLaunch != true
		!ifdef SERVICES
			${RunSegment} Services
		!endif
	${EndIf}

	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!endif
	!endif
	Pop $0
FunctionEnd

Function PreSecondary
	Push $0
	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!endif
	!endif

	${RunSegment} Custom

	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!endif
	!endif
	Pop $0
FunctionEnd

Function PreExec
	Push $0
	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!endif
	!endif

	${RunSegment} Custom

	${If} $SecondaryLaunch != true
		!ifdef REGISTERDLL
			${RunSegment} RegisterDLL
		!endif
	${EndIf}

	${RunSegment} RefreshShellIcons
	${RunSegment} WorkingDirectory

	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!endif
	!endif
	Pop $0
FunctionEnd

Function PreExecPrimary
	Push $0
	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!endif
	!endif

	${RunSegment} Custom
	${RunSegment} Core

	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!endif
	!endif
	Pop $0
FunctionEnd

Function PreExecSecondary
	Push $0
	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!endif
	!endif

	${RunSegment} Custom

	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!endif
	!endif
	Pop $0
FunctionEnd

Function Execute
	Push $0
	Push $1
	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!endif
	!endif

	!ifmacrodef OverrideExecuteFunction
		!insertmacro OverrideExecuteFunction
	!else
		!ifmacrodef PreExecExecute
			!insertmacro PreExecExecute
		!endif
		${EmptyWorkingSet}
		ClearErrors
		${ReadLauncherConfig} $0 Launch HideCommandLineWindow
		${If} $0 == true
			StrCpy $ExecString "$ExecString $Parameters"
			ExecDos::exec /TOSTACK $ExecString
			Pop $0
		${Else}
			${IfNot} ${Errors}
			${AndIf} $0 != false
				${InvalidValueError} [Launch]:HideCommandLineWindow $0
			${EndIf}
			${If} $WaitForProgram != false
				!ifdef ExecAsUser
					${ConfigReads} `${CONFIG}` ExecAsAdmin= $0
					${If} $0 == true
						StrCpy $ExecString "$ExecString $Parameters"
						ExecWait $ExecString
					${Else}
						${StdUtils.ExecShellAsUser} $0 "$ExecString" "" "$Parameters"
						Sleep 1000
						${GetFileName} $ProgramExecutable $1
						${EmptyWorkingSet}
						${Do}
							${ProcessWaitClose} $1 -1 $R9
							${IfThen} $R9 > 0 ${|} ${Continue} ${|}
						${LoopWhile} $R9 > 0
					${EndIf}
				!else
					ExecWait $ExecString
				!endif
			${Else}
				!ifdef ExecAsUser
					${StdUtils.ExecShellAsUser} $0 "$ExecString" "" "$Parameters"
				!else
					Exec $ExecString
				!endif
			${EndIf}
		${EndIf}
		!ifmacrodef PostExecWaitCommand
			!insertmacro PostExecWaitCommand
		!endif
		${If} $WaitForProgram != false
			ClearErrors
			${ReadLauncherConfig} $0 Launch WaitForOtherInstances
			${If} $0 == true
			${OrIf} ${Errors}
				${GetFileName} $ProgramExecutable $1
				${EmptyWorkingSet}
				${Do}
					!ifdef Sleep1000
						!ifndef Sleep2000
							Sleep 1000
						!endif
					!endif
					!ifdef Sleep2000
						!ifndef Sleep1000
							Sleep 2000
						!endif
					!endif
					${ProcessWaitClose} $1 -1 $R9
					${IfThen} $R9 > 0 ${|} ${Continue} ${|}
					StrCpy $0 1
					${Do}
						!ifdef Sleep1000
							!ifndef Sleep2000
								Sleep 1000
							!endif
						!endif
						!ifdef Sleep2000
							!ifndef Sleep1000
								Sleep 2000
							!endif
						!endif
						ClearErrors
						${ReadLauncherConfig} $2 Launch WaitForEXE$0
						${IfThen} ${Errors} ${|} ${ExitDo} ${|}
						${ParseLocations} $2
						${ProcessWaitClose} $2 -1 $R9
						${IfThen} $R9 > 0 ${|} ${ExitDo} ${|}
						IntOp $0 $0 + 1
					${Loop}
				${LoopWhile} $R9 > 0
			${ElseIf} $0 != false
				${InvalidValueError} [Launch]:WaitForOtherInstances $0
			${EndIf}
		${EndIf}
	!endif

	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!endif
	!endif
	Pop $1
	Pop $0
FunctionEnd

Function PostPrimary
	Push $0
	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!endif
	!endif

	${If} $SecondaryLaunch != true
		!ifdef REGISTERDLL
			${RunSegment} RegisterDLL
		!endif
		!ifdef SERVICES
			${RunSegment} Services
		!endif
		${RunSegment} RegistryValueDelete
	${EndIf}

	!ifdef REGISTRY
		${RunSegment} RegistryValueBackupDelete
		${If} $SecondaryLaunch != true
			${RunSegment} RegistryCopyKeys
		${EndIf}
		${RunSegment} RegistryKeys
		${RunSegment} RegistryCleanup
		!ifdef SYSTEMWIDE_DISABLEREDIR
			;=== Registry uses Enable/disable redir.
			;=== this is a fail-safe mechanism.
			!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
				${If} ${RunningX64}
					System::Call `${DISABLEREDIR}`
				${EndIf}
			!else
				ReadEnvStr $0 ${APP}
				${If} $0 == ${APP64}
					System::Call `${DISABLEREDIR}`
				${EndIf}
			!endif
		!endif
	!endif

	${If} $SecondaryLaunch != true
		${RunSegment} Qt
		${RunSegment} FilesCleanup
	${EndIf}

	${RunSegment} DirectoriesCleanup
	${RunSegment} DirectoriesMove
	${RunSegment} FilesMove
	${RunSegment} RunLocally
	${RunSegment} Temp
	${RunSegment} Custom

	${If} $SecondaryLaunch != true
		${RunSegment} FilesBackup
	${EndIf}

	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!endif
	!endif
	Pop $0
FunctionEnd

Function PostSecondary
	Push $0
	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!endif
	!endif

	${RunSegment} Custom

	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!endif
	!endif
	Pop $0
FunctionEnd

Function Post
	Push $0
	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!endif
	!endif
	${RunSegment} RefreshShellIcons
	${RunSegment} Custom

	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!endif
	!endif
	Pop $0
FunctionEnd

Function Unload
	Push $0
	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!endif
	!endif

	${If} $SecondaryLaunch != true
		!ifdef REGISTERDLL
			${RunSegment} RegisterDLL
		!endif
		!ifdef SERVICES
			${RunSegment} Services
		!endif
		${RunSegment} FilesCleanup
		${RunSegment} DirectoriesCleanup
	${EndIf}

	${RunSegment} Core
	${RunSegment} Custom

	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!endif
	!endif
	Pop $0
FunctionEnd

!define CallPS `!insertmacro CallPS`
!macro CallPS _func _rev
	!if ${_rev} == +
		Call ${_func}
	!endif
	${If} $SecondaryLaunch == true
		Call ${_func}Secondary
	${Else}
		Call ${_func}Primary
	${EndIf}
	!if ${_rev} != +
		Call ${_func}
	!endif
!macroend

Section
	Push $0
	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${DISABLEREDIR}`
			${EndIf}
		!endif
	!endif

	Call Init
	System::Call 'Kernel32::OpenMutex(i1048576, b0, t"PortableApps.comLauncher${APPNAME}-${APPNAME}::Starting") i.R0 ?e'
	System::Call 'Kernel32::CloseHandle(iR0)'
	Pop $R9
	${If} $R9 <> 2
		MessageBox MB_ICONSTOP $(LauncherAlreadyStarting)
		Quit
	${EndIf}
	System::Call 'Kernel32::OpenMutex(i1048576, i0, t"PortableApps.comLauncher${APPNAME}-${APPNAME}::Stopping") i.R0 ?e'
	System::Call 'Kernel32::CloseHandle(iR0)'
	Pop $R9
	${If} $R9 <> 2
		MessageBox MB_ICONSTOP $(LauncherAlreadyStopping)
		Quit
	${EndIf}
	${IfNot} ${FileExists} `${RUNTIME}`
	${OrIf} $SecondaryLaunch == true
		${If} $SecondaryLaunch != true
			System::Call 'Kernel32::CreateMutex(i0, i0, t"PortableApps.comLauncher${APPNAME}-${APPNAME}::Starting") i.r0'
			StrCpy $StatusMutex $0
		${EndIf}
		${CallPS} Pre +
		${CallPS} PreExec +
		${If} $SecondaryLaunch != true
			StrCpy $0 $StatusMutex
			System::Call 'Kernel32::CloseHandle(ir0) ?e'
			Pop $R9
		${EndIf}
		Call Execute
	${Else}
		MessageBox MB_ICONSTOP $(LauncherCrashCleanup)
	${EndIf}
	${If} $SecondaryLaunch != true
		System::Call 'Kernel32::CreateMutex(i0, i0, t"PortableApps.comLauncher${APPNAME}-${APPNAME}::Stopping")'
	${EndIf}
	${If} $WaitForProgram != false
		${CallPS} Post -
	${EndIf}
	Call Unload

	!ifdef SYSTEMWIDE_DISABLEREDIR
		!ifdef FORCE_SYSTEMWIDE_DISABLEREDIR
			${If} ${RunningX64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!else
			ReadEnvStr $0 ${APP}
			${If} $0 == ${APP64}
				System::Call `${ENABLEREDIR}`
			${EndIf}
		!endif
	!endif
	Pop $0
SectionEnd

Function .onInstFailed
	Call Unload
FunctionEnd