/*
████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████
██████████████████████████████████ D o o m S t o r m ███████████████████████████
████████████████████████████████████████████████████████████████████████████████
███████████████████████████████████▒████████████████████████████████████████████
███████████████████████████████████▒████████████████████████████████████████████
██████████████████████████████████▒▒████████████████████████████████████████████
██████████████████████████████████▒█▒███████████████████████████████████████████
██████████████████████████████████▒█▒███████████████████████████████████████████
█████████████████████████████████▒██▒███████████████████████████████████████████
█████████████████████████████████▒██▒███████████████████████████████████████████
█████████████████████████████████▒██▒███████████████████████████████████████████
████████████████████████████████▒███▒███████████████████████████████████████████
████████████████████████████████▒████▒██████████████████████████████████████████
████████████████████████████████▒████▒██████████████████████████████████████████
███████████████████████████████▒█████▒██████████████████████████████████████████
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒█████▒██▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
█████████████████████████████████████▒██▒███████████████████████████████████████
██████████████████████████████████████▒▒████████████████████████████████████████
██████████████████████████████████████▒▒████████████████████████████████████████
██████████████████████████████████████▒█████████████████████████████████████████
██████████████████████████████████████▒█████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████
████████████████████████████████████████████████████████████████████████████████
*/

; === NSIS 3 Support ===
Unicode true
ManifestDPIAware true

; === Cert ===
!if /FileExists ..\..\..\..\Cert\Certificate.nsh
    !include ..\..\..\..\Cert\Certificate.nsh
!endif

!define BUILDDATE   "${__DATE__}"
!define COMMENTS    "Developed by DoomStorm"
!define COPYRIGHT   "IObit."
!define APPNAME     "IObit Driver Booster 5"
!define APP         "DriverBooster"
!define APPVER      "0.0.0.0"
!define VER         "5.x.x.x"
!define APPEXE      "DriverBooster.exe"
!define APPDIR      "DriverBooster"
!define RUNASADMIN

; === Define Registry ===
!define REGKEY1 "HKEY_LOCAL_MACHINE\SOFTWARE\IObit\Driver Booster"

; === Define Directories ===
!define LOCALDIR1 "$APPDATA"
!define SUBDIR1 "\IObit"
!define PORTABLEDIR1 "$SETTINGSDIR\AppData"

!define LOCALDIR3 "$PROGRAMDIR"
!define SUBDIR3 "\LocalData"
!define PORTABLEDIR3 "$SETTINGSDIR\LocalData"

!define LOCALDIR4 "$PROGRAMDIR"
!define SUBDIR4 "\ScanData"
!define PORTABLEDIR4 "$SETTINGSDIR\ScanData"

!define LOCALDIR5 "$PROGRAMDIR"
!define SUBDIR5 "\Update"
!define PORTABLEDIR5 "$SETTINGSDIR\Update"

!define LOCALDIR6 "$PROFILE\AppData\LocalLow"
!define SUBDIR6 "\IObit"
!define PORTABLEDIR6 "$SETTINGSDIR\LocalLow"

!define LOCALDIR7 "$WINDIR"
!define SUBDIR7 "\IObit"
!define PORTABLEDIR7 "$SETTINGSDIR\LocalLow"

; (all users):
!define LOCALDIR2 "$APPDATA"
!define SUBDIR2 "\IObit"
!define PORTABLEDIR2 "$SETTINGSDIR\ProgramData\IObit"

; === Define File ===
!define LOCALFILE1 "$SYSDIR\Tasks\Driver Booster SkipUAC ($CUSTOM_LOGGEDINUSER)"
!define LOCALFILE2 "$SYSDIR\Tasks\Driver Booster Scheduler"

; === Best Compression ===
SetCompress auto
SetCompressor /SOLID lzma
SetCompressorDictSize 32
SetDatablockOptimize on

; === Include ===
!include Include\Launcher.nsh
!include Include\Macros.nsh

; === Set basic information ===
Name "${APPNAME} Portable"
OutFile "..\..\${APP}Portable.exe"
Icon "${APP}.ico"

Var CUSTOM_LOGGEDINUSER
Var CUSTOM_BOL_HWINFO
Var CUSTOM_HWINFOFILE
Var DOWNLOADPATH
Var BACKUPPATH
Var LNG

Function Init
	; Get the user name for the current user.
	System::Call "advapi32::GetUserName(t .r0, *i ${NSIS_MAX_STRLEN} r1) i.r2"
	StrCpy $CUSTOM_LOGGEDINUSER $0
	; Check for installed version of HWiNFO32.
	ReadRegStr $0 HKLM "SYSTEM\CurrentControlSet\services\HWiNFO32" ""
	${IF} $0 == ""
		StrCpy $CUSTOM_BOL_HWINFO '0' ; If not found, we use the portable service.
		nsExec::ExecToStack	'"$PROGRAMDIR\HWiNFO\HWiNFO.exe" /brandname'
	${Else}
		StrCpy $CUSTOM_BOL_HWINFO '1' ; If found, we use the installed service.
	${EndIf}
	
	; === Backup local registry key ===
	${registry::BackupLocal} "${REGKEY1}"
	
	; === Backup local directories ===
	${directory::BackupLocal} "${LOCALDIR1}" "${SUBDIR1}"
	${directory::BackupLocal} "${LOCALDIR3}" "${SUBDIR3}"
	${directory::BackupLocal} "${LOCALDIR4}" "${SUBDIR4}"
	${directory::BackupLocal} "${LOCALDIR5}" "${SUBDIR5}"
	${directory::BackupLocal} "${LOCALDIR6}" "${SUBDIR6}"
	${directory::BackupLocal} "${LOCALDIR7}" "${SUBDIR7}"
	; (all users):
	${directory::BackupLocalAll} "${LOCALDIR2}" "${SUBDIR2}"
	
	; === Default settings ===
	IfFileExists "${PORTABLEDIR1}\*.*" +2
		CreateDirectory "${PORTABLEDIR1}\Driver Booster"
	WriteINIStr "${PORTABLEDIR1}\Driver Booster\Config.ini" "General" "AutoRun" "0"
	WriteINIStr "${PORTABLEDIR1}\Driver Booster\Config.ini" "General" "CloseAction" "0"
	WriteINIStr "${PORTABLEDIR1}\Driver Booster\Config.ini" "Scan" "Schedule" "-1"
	WriteINIStr "${PORTABLEDIR1}\Driver Booster\Config.ini" "AutoUpdate" "UpdateType" "0"
	WriteINIStr "${PORTABLEDIR1}\Driver Booster\Config.ini" "Drivers" "AutoInst" "0"
	DeleteINIStr "${PORTABLEDIR1}\Driver Booster\Config.ini" "General" "Language"
	WriteINIStr "${PORTABLEDIR1}\Driver Booster\Config.ini" "Promote" "Speedup" "0"
	WriteINIStr "${PORTABLEDIR1}\Driver Booster\Config.ini" "Promote" "ASCShow" "0"
	
	; === UserDefaultLang ===
	; Launcher will change app language according Windows language,
	; see also: http://medicinecollections.zat.su/lngcode.html.
	StrCmp $LANGID "1025" "" +2
		StrCpy $LNG "Arabic"
	StrCmp $LANGID "1026" "" +2
		StrCpy $LNG "Bulgarian"
	StrCmp $LANGID "1028" "" +2
		StrCpy $LNG "ChineseTrad"
	StrCmp $LANGID "1029" "" +2
		StrCpy $LNG "Czech"
	StrCmp $LANGID "1030" "" +2
		StrCpy $LNG "Danish"
	StrCmp $LANGID "1031" "" +2
		StrCpy $LNG "German"
	StrCmp $LANGID "1032" "" +2
		StrCpy $LNG "Greek"
	StrCmp $LANGID "1033" "" +2
		StrCpy $LNG "English"
	StrCmp $LANGID "1034" "" +2
		StrCpy $LNG "Spanish"
	StrCmp $LANGID "1035" "" +2
		StrCpy $LNG "Finnish"
	StrCmp $LANGID "1036" "" +2
		StrCpy $LNG "French"
	StrCmp $LANGID "1037" "" +2
		StrCpy $LNG "Hebrew"
	StrCmp $LANGID "1038" "" +2
		StrCpy $LNG "Hungarian"
	StrCmp $LANGID "1040" "" +2
		StrCpy $LNG "Italian"
	StrCmp $LANGID "1041" "" +2
		StrCpy $LNG "Japanese"
	StrCmp $LANGID "1042" "" +2
		StrCpy $LNG "Korean"
	StrCmp $LANGID "1043" "" +2
		StrCpy $LNG "Dutch"
	StrCmp $LANGID "1045" "" +2
		StrCpy $LNG "Polish"
	StrCmp $LANGID "1046" "" +2
		StrCpy $LNG "Portuguese (PT-BR)"
	StrCmp $LANGID "1048" "" +2
		StrCpy $LNG "Romanian"
	StrCmp $LANGID "1049" "" +2
		StrCpy $LNG "Russian"
	StrCmp $LANGID "1050" "" +2
		StrCpy $LNG "Croatian"
	StrCmp $LANGID "1052" "" +2
		StrCpy $LNG "Albanian"
	StrCmp $LANGID "1053" "" +2
		StrCpy $LNG "Swedish"
	StrCmp $LANGID "1054" "" +2
		StrCpy $LNG "Thai"
	StrCmp $LANGID "1055" "" +2
		StrCpy $LNG "Turkish"
	StrCmp $LANGID "1058" "" +2
		StrCpy $LNG "Ukrainian"
	StrCmp $LANGID "1059" "" +2
		StrCpy $LNG "Belarusian"
	StrCmp $LANGID "1060" "" +2
		StrCpy $LNG "Slovenian"
	StrCmp $LANGID "1066" "" +2
		StrCpy $LNG "Vietnamese"
	StrCmp $LANGID "1104" "" +2
		StrCpy $LNG "Mongolian"
	StrCmp $LANGID "1121" "" +2
		StrCpy $LNG "Nepali"
	StrCmp $LANGID "2052" "" +2
		StrCpy $LNG "ChineseSimp"
	StrCmp $LANGID "2070" "" +2
		StrCpy $LNG "Portuguese (PT-PT)"
	StrCmp $LANGID "2074" "" +2
		StrCpy $LNG "Serbian (Latin)"
	StrCmp $LANGID "3098" "" +2
		StrCpy $LNG "Serbian (Cyrillic)"
	ReadINIStr $0 "$EXEDIR\${APP}Portable.ini" "${APP}Portable" "UserDefaultLang"
	StrCmp $0 "" "" +3
		WriteINIStr "$EXEDIR\${APP}Portable.ini" "${APP}Portable" "UserDefaultLang" "true"
		StrCpy $0 "true"
	StrCmp $0 "true" CheckLanguage UserDefaultLangEnd
	CheckLanguage:
		StrCmp $LNG "" UserDefaultLangEnd ; use last used language if no supported language on host computer.
		StrCmp $LNG "English" ChangeLanguage ; change language without checking existence of language files if language is English.
			IfFileExists "$PROGRAMDIR\Language\$LNG.lng" ChangeLanguage UserDefaultLangEnd
	ChangeLanguage:
		WriteINIStr "${PORTABLEDIR1}\Driver Booster\Config.ini" "Main" "Language" "$LNG"
	UserDefaultLangEnd:


	; === PortableDownloadPath ===
	ReadINIStr $0 "$EXEDIR\${APP}Portable.ini" "${APP}Portable" "PortableDownloadPath"
	StrCmp $0 "" "" +3
		WriteINIStr "$EXEDIR\${APP}Portable.ini" "${APP}Portable" "PortableDownloadPath" "true"
		StrCpy $0 "true"

	; === DownloadPath ===
	ClearErrors
	ReadINIStr $1 "$EXEDIR\${APP}Portable.ini" "${APP}Portable" "DownloadPath"
	IfErrors "" +2
		WriteINIStr "$EXEDIR\${APP}Portable.ini" "${APP}Portable" "DownloadPath" ""

	StrCmp $0 "true" UsePortableDownloadPath CheckDownloadPath

	UsePortableDownloadPath:
		StrCpy $DOWNLOADPATH "$EXEDIR\Data\Download"
		WriteINIStr "$EXEDIR\${APP}Portable.ini" "${APP}Portable" "PortableDownloadPath" "true"
		Goto SetDownloadPath

	CheckDownloadPath:
		StrCmp $1 "" UsePortableDownloadPath
			StrCpy $DOWNLOADPATH "$ROOTDIR\$1"

	SetDownloadPath:
		CreateDirectory "$DOWNLOADPATH"
		WriteINIStr "${PORTABLEDIR1}\Driver Booster\Config.ini" "Drivers" "DownPath" "$DOWNLOADPATH\"

	; === PortableBackupPath ===
	ReadINIStr $0 "$EXEDIR\${APP}Portable.ini" "${APP}Portable" "PortableBackupPath"
	StrCmp $0 "" "" +3
		WriteINIStr "$EXEDIR\${APP}Portable.ini" "${APP}Portable" "PortableBackupPath" "true"
		StrCpy $0 "true"

	; === BackupPath ===
	ClearErrors
	ReadINIStr $1 "$EXEDIR\${APP}Portable.ini" "${APP}Portable" "BackupPath"
	IfErrors "" +2
		WriteINIStr "$EXEDIR\${APP}Portable.ini" "${APP}Portable" "BackupPath" ""

	StrCmp $0 "true" UsePortableBackupPath CheckBackupPath

	UsePortableBackupPath:
		StrCpy $BACKUPPATH "$EXEDIR\Data\Backups"
		WriteINIStr "$EXEDIR\${APP}Portable.ini" "${APP}Portable" "PortableBackupPath" "true"
		Goto SetBackupPath

	CheckBackupPath:
		StrCmp $1 "" UsePortableBackupPath
			StrCpy $BACKUPPATH "$ROOTDIR\$1"

	SetBackupPath:
		CreateDirectory "$BACKUPPATH"
		WriteINIStr "${PORTABLEDIR1}\Driver Booster\Config.ini" "Drivers" "BackPath" "$BACKUPPATH\"

	; === Restore portable directories ===
	${directory::RestorePortable} "${LOCALDIR1}" "${SUBDIR1}" "${PORTABLEDIR1}"
	${directory::RestorePortable} "${LOCALDIR3}" "${SUBDIR3}" "${PORTABLEDIR3}"
	${directory::RestorePortable} "${LOCALDIR4}" "${SUBDIR4}" "${PORTABLEDIR4}"
	${directory::RestorePortable} "${LOCALDIR5}" "${SUBDIR5}" "${PORTABLEDIR5}"
	${directory::RestorePortable} "${LOCALDIR6}" "${SUBDIR6}" "${PORTABLEDIR6}"
	${directory::RestorePortable} "${LOCALDIR7}" "${SUBDIR7}" "${PORTABLEDIR7}"
	; (all users):
	${directory::RestorePortableAll} "${LOCALDIR2}" "${SUBDIR2}" "${PORTABLEDIR2}"
	
	; === Backup local file ===
	${file::BackupLocal} "${LOCALFILE1}"
	${file::BackupLocal} "${LOCALFILE2}"
FunctionEnd

Section "Main"
	Call DefaultVar

	Call CheckStart

	Call Init

	Call RuntimeData

	; === Launch ===
	SetOutPath "$PROGRAMDIR" ; lock rename!.
	StrCmp `$PARAMETERS` `` LaunchWithoutParameters LaunchWithParameters
	LaunchWithoutParameters:
		ExecWait `"$PROGRAMDIR\$PROGRAMEXE"$PROGRAMSWITCH`
		Goto CheckStillRunning
	LaunchWithParameters:
		ExecWait `"$PROGRAMDIR\$PROGRAMEXE"$PROGRAMSWITCH $PARAMETERS`
	CheckStillRunning:
		; Wait until app closed:
		FindProcDLL::WaitProcEnd "$PROGRAMEXE" -1 ; FindProcDLL modified by hnedka.
		FindProcDLL::FindProc "$PROGRAMEXE"
		StrCmp $R0 "1" "" +3
			Sleep 2000
			Goto -3

	Call Close

	Call CleanUp

	Call TheEnd
SectionEnd

Function Close
	; Take care of the Tasks, Sorry if you got the APP installed =(.
	${If} $ARCHITECTURE == "x64"
		System::Call `kernel32::Wow64EnableWow64FsRedirection(i0)`
		${If} ${FileExists} '$SYSDIR\Tasks\Driver Booster SkipUAC ($CUSTOM_LOGGEDINUSER)'
			nsExec::ExecToStack '$SYSDIR\SCHTASKS.EXE /Delete /TN "Driver Booster SkipUAC ($CUSTOM_LOGGEDINUSER)" /F'
		${EndIf}
		${If} ${FileExists} '$SYSDIR\Tasks\Driver Booster Scheduler'
			nsExec::ExecToStack '$SYSDIR\SCHTASKS.EXE /Delete /TN "Driver Booster Scheduler" /F'
		${EndIf}
		System::Call `kernel32::Wow64EnableWow64FsRedirection(i1)`
	${EndIf}

	; === Restore local file ===
	${file::RestoreLocal} "${LOCALFILE1}"
	${file::RestoreLocal} "${LOCALFILE2}"
	
	; === Backup portable directories ===
	${directory::BackupPortable} "${PORTABLEDIR1}" "${LOCALDIR1}" "${SUBDIR1}"
	${directory::BackupPortable} "${PORTABLEDIR3}" "${LOCALDIR3}" "${SUBDIR3}"
	${directory::BackupPortable} "${PORTABLEDIR4}" "${LOCALDIR4}" "${SUBDIR4}"
	${directory::BackupPortable} "${PORTABLEDIR5}" "${LOCALDIR5}" "${SUBDIR5}"
	${directory::BackupPortable} "${PORTABLEDIR6}" "${LOCALDIR6}" "${SUBDIR6}"
	${directory::BackupPortable} "${PORTABLEDIR7}" "${LOCALDIR7}" "${SUBDIR7}"
	; (all users):
	${directory::BackupPortableAll} "${PORTABLEDIR2}" "${LOCALDIR2}" "${SUBDIR2}"

	; === Restore local directories ===
	${directory::RestoreLocal} "${LOCALDIR1}" "${SUBDIR1}"
	${directory::RestoreLocal} "${LOCALDIR3}" "${SUBDIR3}"
	${directory::RestoreLocal} "${LOCALDIR4}" "${SUBDIR4}"
	${directory::RestoreLocal} "${LOCALDIR5}" "${SUBDIR5}"
	${directory::RestoreLocal} "${LOCALDIR6}" "${SUBDIR6}"
	${directory::RestoreLocal} "${LOCALDIR7}" "${SUBDIR7}"
	; (all users):
	${directory::RestoreLocalAll} "${LOCALDIR2}" "${SUBDIR2}"

	; === Restore local registry key ===
	${registry::RestoreLocal} "${REGKEY1}"
		
	; This will be omitted if the installed Service is found.
	${If} $CUSTOM_BOL_HWINFO != '0'
		; Check the registry for this entry.
		ReadRegStr $0 HKLM 'SYSTEM\CurrentControlSet\services\HWiNFO32' ImagePath
		StrCpy $1 $0 4 ; Copy first 4 characters of the string.
		${If} $1 == "\??\" ; Checks if "\??\" is present.
			StrCpy $CUSTOM_HWINFOFILE $0 "" 4 ; Remove the "\??\" path of eg. "\??\C:\Windows\system32\drivers\HWiNFO32.SYS"
		${Else}
			StrCpy $CUSTOM_HWINFOFILE $0 ; If they don't need to be removed, use this.
		${EndIf}
		; Remove quotes, if necessary.
		StrCpy $1 "$0" 1
		${IfThen} $1 == `"` ${|} StrCpy $0 "$0" "" 1 ${|}
		StrCpy $1 "$0" "" -1
		${IfThen} $1 == `"` ${|} StrCpy $0 "$0" "" -1 ${|}
		; Stop the service.
		nsExec::ExecToStack '"$SYSDIR\SC.EXE" STOP HWiNFO32'
		nsExec::ExecToStack '"$SYSDIR\SC.EXE" DELETE HWiNFO32'
		; Delete the registry entries.
		DeleteRegKey HKLM 'SYSTEM\ControlSet001\services\HWiNFO32'
		DeleteRegKey HKLM 'SYSTEM\CurrentControlSet\services\HWiNFO32'
		; Delete the the file - "$SYSDIR\drivers\HWiNFO32.SYS".
		Delete '$CUSTOM_HWINFOFILE'
	${EndIf}
FunctionEnd

Function CleanUp
	; === Delete registry key if empty ===
	registry::_DeleteKeyEmpty /NOUNLOAD "HKEY_LOCAL_MACHINE\SOFTWARE\IObit"
	; === Force remove folders ===
	RMDir /r "$PROGRAMDIR\LatestNews"
	SetShellVarContext all
	RMDir /r "$APPDATA\ProductData"
	SetShellVarContext current

FunctionEnd

Function TheEnd
	; === Unload plug-ins ===
	registry::_Unload ; unload registry plug-in

	; === Remove runtime data ===
	FileClose $RUNTIMEDATA ; unlock file
		Delete "$EXEDIR\Data\${APP}PortableRuntimeData.ini"
FunctionEnd
