From aeb578411327dd6d9c5b5dfea862aa154c6602fc Mon Sep 17 00:00:00 2001 From: Ahrimdon Date: Tue, 19 Nov 2024 15:03:36 -0500 Subject: [PATCH] maint(iw7_Installer.nsi) better file/error handling, silent argument, launch options --- installer/iw7_Installer.nsi | 103 +- installer/tools/Include/FileFunc.nsh | 2012 ++++++++++++++++++ installer/tools/Include/x64.nsh | 120 ++ installer/tools/Stubs/lzma_solid-x86-unicode | Bin 0 -> 38912 bytes 4 files changed, 2225 insertions(+), 10 deletions(-) create mode 100644 installer/tools/Include/FileFunc.nsh create mode 100644 installer/tools/Include/x64.nsh create mode 100644 installer/tools/Stubs/lzma_solid-x86-unicode diff --git a/installer/iw7_Installer.nsi b/installer/iw7_Installer.nsi index 74fbe412..b7cb77a5 100644 --- a/installer/iw7_Installer.nsi +++ b/installer/iw7_Installer.nsi @@ -1,11 +1,20 @@ +SetCompressor /SOLID lzma +SetCompressorDictSize 64 +; /SOLID: Improves compression ratio by treating files as a single stream +; SetCompressorDictSize: Controls compression memory and efficiency +; - Larger values (32-64) improve compression but use more memory +; - Smaller values (16-32) use less memory but compress less effectively + !include "MUI2.nsh" !include "WinVer.nsh" !include "nsDialogs.nsh" +!include "FileFunc.nsh" +!include "x64.nsh" ; Constants !define PRODUCT_NAME "IW7-Mod" -!define PRODUCT_DESCRIPTION "Call of Duty Infinite Warfare Client" -!define COPYRIGHT "Installer created by Ahrimdon (FOSS)" +!define PRODUCT_DESCRIPTION "Call of Duty: Infinite Warfare - Client" +!define COPYRIGHT "Copyright © 2024 AlterWare" !define PRODUCT_VERSION "1.0.0.0" !define SETUP_VERSION "1.0.0.0" @@ -61,12 +70,70 @@ ShowUninstDetails show ; Languages !insertmacro MUI_LANGUAGE "English" +; Conditional Debug Details +!ifdef DEBUG + ShowInstDetails always +!endif + Function .onInit + ; X64 Filesystem Redirection + ${If} ${RunningX64} + ${DisableX64FSRedirection} + ${EndIf} + ; Check for Silent Install arguments + ${GetParameters} $R0 + ${GetOptions} $R0 "/s" $0 + IfErrors +3 + SetSilent silent + Goto done + + ${GetOptions} $R0 "-s" $0 + IfErrors +3 + SetSilent silent + Goto done + + ; GUI install MessageBox MB_OKCANCEL|MB_ICONINFORMATION "Place the installer in your Call of Duty Infinite Warfare game folder. Click OK to continue or Cancel to exit." IDOK done Abort done: FunctionEnd +; Check and Cleanup Old Files +Section "Cleanup Old Files" + ; Check if each file exists before deleting + ${If} ${FileExists} "$INSTDIR\iw7-mod.exe" + Delete "$INSTDIR\iw7-mod.exe" + ${EndIf} + + ${If} ${FileExists} "$INSTDIR\runner.exe" + Delete "$INSTDIR\runner.exe" + ${EndIf} + + ${If} ${FileExists} "$INSTDIR\tlsdll.dll" + Delete "$INSTDIR\tlsdll.dll" + ${EndIf} + + ; Directory cleanup + ${If} ${FileExists} "$INSTDIR\iw7-mod\custom_scripts" + RMDir /r "$INSTDIR\iw7-mod\custom_scripts" + ${EndIf} + + ${If} ${FileExists} "$INSTDIR\iw7-mod\sounddata" + RMDir /r "$INSTDIR\iw7-mod\sounddata" + ${EndIf} + + ${If} ${FileExists} "$INSTDIR\iw7-mod\ui_scripts" + RMDir /r "$INSTDIR\iw7-mod\ui_scripts" + ${EndIf} + + ${If} ${FileExists} "$INSTDIR\iw7-mod\zone" + RMDir /r "$INSTDIR\iw7-mod\zone" + ${EndIf} + + ; IfFileExists "$INSTDIR\*.*" 0 +2 + ; RMDir /r "$INSTDIR\*.*" +SectionEnd + ; Sections Section "Main Application" SecMain SetOutPath $INSTDIR @@ -98,15 +165,35 @@ Function finishpageaction CreateShortcut "$DESKTOP\${PRODUCT_NAME}.lnk" "$INSTDIR\iw7-mod.exe" "" "$INSTDIR\iw7-mod.exe" FunctionEnd -; Uninstaller Sections +; Display informational message after silent installation is complete +Function .onInstSuccess + ${If} ${Silent} + MessageBox MB_ICONINFORMATION|MB_OKCANCEL "Install complete! Launch IW7-Mod?" IDOK launchGame + Return + + launchGame: + Exec "$INSTDIR\iw7-mod.exe" + ${EndIf} +FunctionEnd + +; Uninstaller Section "Uninstall" + ; ; Check for Silent Uninstall arguments + ; ${GetParameters} $R0 + ; ${GetOptions} $R0 "/s" $0 + ; IfErrors +3 + ; SetSilent silent + + ; ${GetOptions} $R0 "-s" $0 + ; IfErrors +3 + ; SetSilent silent + + Delete "$DESKTOP\${PRODUCT_NAME}.lnk" Delete $INSTDIR\iw7-mod.exe Delete $INSTDIR\runner.exe Delete $INSTDIR\tlsdll.dll - Delete "$DESKTOP\${PRODUCT_NAME}.lnk" Delete $INSTDIR\main\server_mp.cfg Delete $INSTDIR\main\server_zm.cfg - Delete "$INSTDIR\!launch_iw7_mod.bat" Delete "$INSTDIR\!start_mp_server.bat" Delete "$INSTDIR\!start_zm_server.bat" @@ -114,9 +201,5 @@ Section "Uninstall" RMDir /r $INSTDIR\iw7-mod Delete "$INSTDIR\Uninstall.exe" - RMDir $INSTDIR + ; RMDir $INSTDIR SectionEnd - -; Create the desktop shortcut based on the checkbox state -; Function .onInstSuccess -; FunctionEnd \ No newline at end of file diff --git a/installer/tools/Include/FileFunc.nsh b/installer/tools/Include/FileFunc.nsh new file mode 100644 index 00000000..f993da4e --- /dev/null +++ b/installer/tools/Include/FileFunc.nsh @@ -0,0 +1,2012 @@ +/* +_____________________________________________________________________________ + + File Functions Header v3.4 +_____________________________________________________________________________ + + 2006 Shengalts Aleksander aka Instructor (Shengalts@mail.ru) + + See documentation for more information about the following functions. + + Usage in script: + 1. !include "FileFunc.nsh" + 2. [Section|Function] + ${FileFunction} "Param1" "Param2" "..." $var + [SectionEnd|FunctionEnd] + + + FileFunction=[Locate|GetSize|DriveSpace|GetDrives|GetTime|GetFileAttributes| + GetFileVersion|GetExeName|GetExePath|GetParameters|GetOptions| + GetOptionsS|GetRoot|GetParent|GetFileName|GetBaseName|GetFileExt| + BannerTrimPath|DirState|RefreshShellIcons] + +_____________________________________________________________________________ + + Thanks to: +_____________________________________________________________________________ + +GetSize + KiCHiK (Function "FindFiles") +DriveSpace + sunjammer (Function "CheckSpaceFree") +GetDrives + deguix (Based on his idea of Function "DetectDrives") +GetTime + Takhir (Script "StatTest") and deguix (Function "FileModifiedDate") +GetFileVersion + KiCHiK (Based on his example for command "GetDLLVersion") +GetParameters + sunjammer (Based on his Function "GetParameters") +GetRoot + KiCHiK (Based on his Function "GetRoot") +GetParent + sunjammer (Based on his Function "GetParent") +GetFileName + KiCHiK (Based on his Function "GetFileName") +GetBaseName + comperio (Based on his idea of Function "GetBaseName") +GetFileExt + opher (author) +RefreshShellIcons + jerome tremblay (author) +*/ + + +;_____________________________________________________________________________ +; +; Macros +;_____________________________________________________________________________ +; +; Change log window verbosity (default: 3=no script) +; +; Example: +; !include "FileFunc.nsh" +; !insertmacro Locate +; ${FILEFUNC_VERBOSE} 4 # all verbosity +; !insertmacro VersionCompare +; ${FILEFUNC_VERBOSE} 3 # no script + +!ifndef FILEFUNC_INCLUDED + +!verbose push 3 +!define /IfNDef _FILEFUNC_VERBOSE 3 +!verbose ${_FILEFUNC_VERBOSE} +!define FILEFUNC_VERBOSE `!insertmacro FILEFUNC_VERBOSE` + +!define FILEFUNC_INCLUDED + +!include Util.nsh + + +!macro FILEFUNC_VERBOSE _VERBOSE + !verbose push 3 + !define /ReDef _FILEFUNC_VERBOSE ${_VERBOSE} + !verbose pop +!macroend + +!macro LocateCall _PATH _OPTIONS _FUNC + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + Push $0 + Push `${_PATH}` + Push `${_OPTIONS}` + GetFunctionAddress $0 `${_FUNC}` + Push `$0` + ${CallArtificialFunction} Locate_ + Pop $0 + !verbose pop +!macroend + +!macro GetSizeCall _PATH _OPTIONS _RESULT1 _RESULT2 _RESULT3 + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + Push `${_PATH}` + Push `${_OPTIONS}` + ${CallArtificialFunction} GetSize_ + Pop ${_RESULT1} + Pop ${_RESULT2} + Pop ${_RESULT3} + !verbose pop +!macroend + +!macro DriveSpaceCall _DRIVE _OPTIONS _RESULT + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + Push `${_DRIVE}` + Push `${_OPTIONS}` + ${CallArtificialFunction} DriveSpace_ + Pop ${_RESULT} + !verbose pop +!macroend + +!macro GetDrivesCall _DRV _FUNC + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + Push $0 + Push `${_DRV}` + GetFunctionAddress $0 `${_FUNC}` + Push `$0` + ${CallArtificialFunction} GetDrives_ + Pop $0 + !verbose pop +!macroend + +!macro GetTimeCall _FILE _OPTION _RESULT1 _RESULT2 _RESULT3 _RESULT4 _RESULT5 _RESULT6 _RESULT7 + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + Push `${_FILE}` + Push `${_OPTION}` + ${CallArtificialFunction} GetTime_ + Pop ${_RESULT1} + Pop ${_RESULT2} + Pop ${_RESULT3} + Pop ${_RESULT4} + Pop ${_RESULT5} + Pop ${_RESULT6} + Pop ${_RESULT7} + !verbose pop +!macroend + +!macro GetFileAttributesCall _PATH _ATTR _RESULT + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + Push `${_PATH}` + Push `${_ATTR}` + ${CallArtificialFunction} GetFileAttributes_ + Pop ${_RESULT} + !verbose pop +!macroend + +!macro GetFileVersionCall _FILE _RESULT + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + Push `${_FILE}` + ${CallArtificialFunction} GetFileVersion_ + Pop ${_RESULT} + !verbose pop +!macroend + +!macro GetExeNameCall _RESULT + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + ${CallArtificialFunction} GetExeName_ + Pop ${_RESULT} + !verbose pop +!macroend + +!macro GetExePathCall _RESULT + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + ${CallArtificialFunction} GetExePath_ + Pop ${_RESULT} + !verbose pop +!macroend + +!macro GetParametersCall _RESULT + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + ${CallArtificialFunction} GetParameters_ + Pop ${_RESULT} + !verbose pop +!macroend + +!macro GetOptionsCall _PARAMETERS _OPTION _RESULT + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + Push `${_PARAMETERS}` + Push `${_OPTION}` + ${CallArtificialFunction} GetOptions_ + Pop ${_RESULT} + !verbose pop +!macroend + +!macro GetOptionsSCall _PARAMETERS _OPTION _RESULT + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + Push `${_PARAMETERS}` + Push `${_OPTION}` + ${CallArtificialFunction} GetOptionsS_ + Pop ${_RESULT} + !verbose pop +!macroend + +!macro GetRootCall _FULLPATH _RESULT + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + Push `${_FULLPATH}` + ${CallArtificialFunction} GetRoot_ + Pop ${_RESULT} + !verbose pop +!macroend + +!macro GetParentCall _PATHSTRING _RESULT + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + Push `${_PATHSTRING}` + ${CallArtificialFunction} GetParent_ + Pop ${_RESULT} + !verbose pop +!macroend + +!macro GetFileNameCall _PATHSTRING _RESULT + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + Push `${_PATHSTRING}` + ${CallArtificialFunction} GetFileName_ + Pop ${_RESULT} + !verbose pop +!macroend + +!macro GetBaseNameCall _FILESTRING _RESULT + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + Push `${_FILESTRING}` + ${CallArtificialFunction} GetBaseName_ + Pop ${_RESULT} + !verbose pop +!macroend + +!macro GetFileExtCall _FILESTRING _RESULT + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + Push `${_FILESTRING}` + ${CallArtificialFunction} GetFileExt_ + Pop ${_RESULT} + !verbose pop +!macroend + +!macro BannerTrimPathCall _PATH _LENGHT _RESULT + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + Push `${_PATH}` + Push `${_LENGHT}` + ${CallArtificialFunction} BannerTrimPath_ + Pop ${_RESULT} + !verbose pop +!macroend + +!macro DirStateCall _PATH _RESULT + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + Push `${_PATH}` + ${CallArtificialFunction} DirState_ + Pop ${_RESULT} + !verbose pop +!macroend + +!macro RefreshShellIconsCall + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + ${CallArtificialFunction} RefreshShellIcons_ + !verbose pop +!macroend + +!define Locate `!insertmacro LocateCall` +!define un.Locate `!insertmacro LocateCall` + +!macro Locate +!macroend + +!macro un.Locate +!macroend + +!macro Locate_ + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + + Exch $2 + Exch + Exch $1 + Exch + Exch 2 + Exch $0 + Exch 2 + Push $3 + Push $4 + Push $5 + Push $6 + Push $7 + Push $8 + Push $9 + Push $R6 + Push $R7 + Push $R8 + Push $R9 + ClearErrors + + StrCpy $3 '' + StrCpy $4 '' + StrCpy $5 '' + StrCpy $6 '' + StrCpy $7 '' + StrCpy $8 0 + StrCpy $R7 '' + + StrCpy $R9 $0 1 -1 + StrCmp $R9 '\' 0 +3 + StrCpy $0 $0 -1 + goto -3 + IfFileExists '$0\*.*' 0 FileFunc_Locate_error + + FileFunc_Locate_option: + StrCpy $R9 $1 1 + StrCpy $1 $1 '' 1 + StrCmp $R9 ' ' -2 + StrCmp $R9 '' FileFunc_Locate_sizeset + StrCmp $R9 '/' 0 -4 + StrCpy $9 -1 + IntOp $9 $9 + 1 + StrCpy $R9 $1 1 $9 + StrCmp $R9 '' +2 + StrCmp $R9 '/' 0 -3 + StrCpy $R8 $1 $9 + StrCpy $R8 $R8 '' 2 + StrCpy $R9 $R8 '' -1 + StrCmp $R9 ' ' 0 +3 + StrCpy $R8 $R8 -1 + goto -3 + StrCpy $R9 $1 2 + StrCpy $1 $1 '' $9 + + StrCmp $R9 'L=' 0 FileFunc_Locate_mask + StrCpy $3 $R8 + StrCmp $3 '' +6 + StrCmp $3 'FD' +5 + StrCmp $3 'F' +4 + StrCmp $3 'D' +3 + StrCmp $3 'DE' +2 + StrCmp $3 'FDE' 0 FileFunc_Locate_error + goto FileFunc_Locate_option + + FileFunc_Locate_mask: + StrCmp $R9 'M=' 0 FileFunc_Locate_size + StrCpy $4 $R8 + goto FileFunc_Locate_option + + FileFunc_Locate_size: + StrCmp $R9 'S=' 0 FileFunc_Locate_gotosubdir + StrCpy $6 $R8 + goto FileFunc_Locate_option + + FileFunc_Locate_gotosubdir: + StrCmp $R9 'G=' 0 FileFunc_Locate_banner + StrCpy $7 $R8 + StrCmp $7 '' +3 + StrCmp $7 '1' +2 + StrCmp $7 '0' 0 FileFunc_Locate_error + goto FileFunc_Locate_option + + FileFunc_Locate_banner: + StrCmp $R9 'B=' 0 FileFunc_Locate_error + StrCpy $R7 $R8 + StrCmp $R7 '' +3 + StrCmp $R7 '1' +2 + StrCmp $R7 '0' 0 FileFunc_Locate_error + goto FileFunc_Locate_option + + FileFunc_Locate_sizeset: + StrCmp $6 '' FileFunc_Locate_default + StrCpy $9 0 + StrCpy $R9 $6 1 $9 + StrCmp $R9 '' +4 + StrCmp $R9 ':' +3 + IntOp $9 $9 + 1 + goto -4 + StrCpy $5 $6 $9 + IntOp $9 $9 + 1 + StrCpy $1 $6 1 -1 + StrCpy $6 $6 -1 $9 + StrCmp $5 '' +2 + IntOp $5 $5 + 0 + StrCmp $6 '' +2 + IntOp $6 $6 + 0 + + StrCmp $1 'B' 0 +3 + StrCpy $1 1 + goto FileFunc_Locate_default + StrCmp $1 'K' 0 +3 + StrCpy $1 1024 + goto FileFunc_Locate_default + StrCmp $1 'M' 0 +3 + StrCpy $1 1048576 + goto FileFunc_Locate_default + StrCmp $1 'G' 0 FileFunc_Locate_error + StrCpy $1 1073741824 + + FileFunc_Locate_default: + StrCmp $3 '' 0 +2 + StrCpy $3 'FD' + StrCmp $4 '' 0 +2 + StrCpy $4 '*.*' + StrCmp $7 '' 0 +2 + StrCpy $7 '1' + StrCmp $R7 '' 0 +2 + StrCpy $R7 '0' + StrCpy $7 'G$7B$R7' + + StrCpy $8 1 + Push $0 + SetDetailsPrint textonly + + FileFunc_Locate_nextdir: + IntOp $8 $8 - 1 + Pop $R8 + + StrCpy $9 $7 2 2 + StrCmp $9 'B0' +3 + GetLabelAddress $9 FileFunc_Locate_findfirst + goto call + DetailPrint 'Search in: $R8' + + FileFunc_Locate_findfirst: + FindFirst $0 $R7 '$R8\$4' + IfErrors FileFunc_Locate_subdir + StrCmp $R7 '.' 0 FileFunc_Locate_dir + FindNext $0 $R7 + StrCmp $R7 '..' 0 FileFunc_Locate_dir + FindNext $0 $R7 + IfErrors 0 FileFunc_Locate_dir + FindClose $0 + goto FileFunc_Locate_subdir + + FileFunc_Locate_dir: + IfFileExists '$R8\$R7\*.*' 0 FileFunc_Locate_file + StrCpy $R6 '' + StrCmp $3 'DE' +4 + StrCmp $3 'FDE' +3 + StrCmp $3 'FD' FileFunc_Locate_precall + StrCmp $3 'F' FileFunc_Locate_findnext FileFunc_Locate_precall + FindFirst $9 $R9 '$R8\$R7\*.*' + StrCmp $R9 '.' 0 +4 + FindNext $9 $R9 + StrCmp $R9 '..' 0 +2 + FindNext $9 $R9 + FindClose $9 + IfErrors FileFunc_Locate_precall FileFunc_Locate_findnext + + FileFunc_Locate_file: + StrCmp $3 'FDE' +3 + StrCmp $3 'FD' +2 + StrCmp $3 'F' 0 FileFunc_Locate_findnext + StrCpy $R6 0 + StrCmp $5$6 '' FileFunc_Locate_precall + FileOpen $9 '$R8\$R7' r + IfErrors +3 + FileSeek $9 0 END $R6 + FileClose $9 + System::Int64Op $R6 / $1 + Pop $R6 + StrCmp $5 '' +2 + IntCmp $R6 $5 0 FileFunc_Locate_findnext + StrCmp $6 '' +2 + IntCmp $R6 $6 0 0 FileFunc_Locate_findnext + + FileFunc_Locate_precall: + StrCpy $9 0 + StrCpy $R9 '$R8\$R7' + + call: + Push $0 + Push $1 + Push $2 + Push $3 + Push $4 + Push $5 + Push $6 + Push $7 + Push $8 + Push $9 + Push $R7 + Push $R8 + StrCmp $9 0 +4 + StrCpy $R6 '' + StrCpy $R7 '' + StrCpy $R9 '' + Call $2 + Pop $R9 + Pop $R8 + Pop $R7 + Pop $9 + Pop $8 + Pop $7 + Pop $6 + Pop $5 + Pop $4 + Pop $3 + Pop $2 + Pop $1 + Pop $0 + + IfErrors 0 +3 + FindClose $0 + goto FileFunc_Locate_error + StrCmp $R9 'StopLocate' 0 +3 + FindClose $0 + goto FileFunc_Locate_clearstack + goto $9 + + FileFunc_Locate_findnext: + FindNext $0 $R7 + IfErrors 0 FileFunc_Locate_dir + FindClose $0 + + FileFunc_Locate_subdir: + StrCpy $9 $7 2 + StrCmp $9 'G0' FileFunc_Locate_end + FindFirst $0 $R7 '$R8\*.*' + StrCmp $R7 '.' 0 FileFunc_Locate_pushdir + FindNext $0 $R7 + StrCmp $R7 '..' 0 FileFunc_Locate_pushdir + FindNext $0 $R7 + IfErrors 0 FileFunc_Locate_pushdir + FindClose $0 + StrCmp $8 0 FileFunc_Locate_end FileFunc_Locate_nextdir + + FileFunc_Locate_pushdir: + IfFileExists '$R8\$R7\*.*' 0 +3 + Push '$R8\$R7' + IntOp $8 $8 + 1 + FindNext $0 $R7 + IfErrors 0 FileFunc_Locate_pushdir + FindClose $0 + StrCmp $8 0 FileFunc_Locate_end FileFunc_Locate_nextdir + + FileFunc_Locate_error: + SetErrors + + FileFunc_Locate_clearstack: + StrCmp $8 0 FileFunc_Locate_end + IntOp $8 $8 - 1 + Pop $R8 + goto FileFunc_Locate_clearstack + + FileFunc_Locate_end: + SetDetailsPrint both + Pop $R9 + Pop $R8 + Pop $R7 + Pop $R6 + Pop $9 + Pop $8 + Pop $7 + Pop $6 + Pop $5 + Pop $4 + Pop $3 + Pop $2 + Pop $1 + Pop $0 + + !verbose pop +!macroend + +!define GetSize `!insertmacro GetSizeCall` +!define un.GetSize `!insertmacro GetSizeCall` + +!macro GetSize +!macroend + +!macro un.GetSize +!macroend + +!macro GetSize_ + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + + Exch $1 + Exch + Exch $0 + Exch + Push $2 + Push $3 + Push $4 + Push $5 + Push $6 + Push $7 + Push $8 + Push $9 + Push $R3 + Push $R4 + Push $R5 + Push $R6 + Push $R7 + Push $R8 + Push $R9 + ClearErrors + + StrCpy $R9 $0 1 -1 + StrCmp $R9 '\' 0 +3 + StrCpy $0 $0 -1 + goto -3 + IfFileExists '$0\*.*' 0 FileFunc_GetSize_error + + StrCpy $3 '' + StrCpy $4 '' + StrCpy $5 '' + StrCpy $6 '' + StrCpy $8 0 + StrCpy $R3 '' + StrCpy $R4 '' + StrCpy $R5 '' + + FileFunc_GetSize_option: + StrCpy $R9 $1 1 + StrCpy $1 $1 '' 1 + StrCmp $R9 ' ' -2 + StrCmp $R9 '' FileFunc_GetSize_sizeset + StrCmp $R9 '/' 0 -4 + + StrCpy $9 -1 + IntOp $9 $9 + 1 + StrCpy $R9 $1 1 $9 + StrCmp $R9 '' +2 + StrCmp $R9 '/' 0 -3 + StrCpy $8 $1 $9 + StrCpy $8 $8 '' 2 + StrCpy $R9 $8 '' -1 + StrCmp $R9 ' ' 0 +3 + StrCpy $8 $8 -1 + goto -3 + StrCpy $R9 $1 2 + StrCpy $1 $1 '' $9 + + StrCmp $R9 'M=' 0 FileFunc_GetSize_size + StrCpy $4 $8 + goto FileFunc_GetSize_option + + FileFunc_GetSize_size: + StrCmp $R9 'S=' 0 FileFunc_GetSize_gotosubdir + StrCpy $6 $8 + goto FileFunc_GetSize_option + + FileFunc_GetSize_gotosubdir: + StrCmp $R9 'G=' 0 FileFunc_GetSize_error + StrCpy $7 $8 + StrCmp $7 '' +3 + StrCmp $7 '1' +2 + StrCmp $7 '0' 0 FileFunc_GetSize_error + goto FileFunc_GetSize_option + + FileFunc_GetSize_sizeset: + StrCmp $6 '' FileFunc_GetSize_default + StrCpy $9 0 + StrCpy $R9 $6 1 $9 + StrCmp $R9 '' +4 + StrCmp $R9 ':' +3 + IntOp $9 $9 + 1 + goto -4 + StrCpy $5 $6 $9 + IntOp $9 $9 + 1 + StrCpy $1 $6 1 -1 + StrCpy $6 $6 -1 $9 + StrCmp $5 '' +2 + IntOp $5 $5 + 0 + StrCmp $6 '' +2 + IntOp $6 $6 + 0 + + StrCmp $1 'B' 0 +4 + StrCpy $1 1 + StrCpy $2 bytes + goto FileFunc_GetSize_default + StrCmp $1 'K' 0 +4 + StrCpy $1 1024 + StrCpy $2 Kb + goto FileFunc_GetSize_default + StrCmp $1 'M' 0 +4 + StrCpy $1 1048576 + StrCpy $2 Mb + goto FileFunc_GetSize_default + StrCmp $1 'G' 0 FileFunc_GetSize_error + StrCpy $1 1073741824 + StrCpy $2 Gb + + FileFunc_GetSize_default: + StrCmp $4 '' 0 +2 + StrCpy $4 '*.*' + StrCmp $7 '' 0 +2 + StrCpy $7 '1' + + StrCpy $8 1 + Push $0 + SetDetailsPrint textonly + + FileFunc_GetSize_nextdir: + IntOp $8 $8 - 1 + Pop $R8 + FindFirst $0 $R7 '$R8\$4' + IfErrors FileFunc_GetSize_show + StrCmp $R7 '.' 0 FileFunc_GetSize_dir + FindNext $0 $R7 + StrCmp $R7 '..' 0 FileFunc_GetSize_dir + FindNext $0 $R7 + IfErrors 0 FileFunc_GetSize_dir + FindClose $0 + goto FileFunc_GetSize_show + + FileFunc_GetSize_dir: + IfFileExists '$R8\$R7\*.*' 0 FileFunc_GetSize_file + IntOp $R5 $R5 + 1 + goto FileFunc_GetSize_findnext + + FileFunc_GetSize_file: + StrCpy $R6 0 + StrCmp $5$6 '' 0 +3 + IntOp $R4 $R4 + 1 + goto FileFunc_GetSize_findnext + FileOpen $9 '$R8\$R7' r + IfErrors +3 + FileSeek $9 0 END $R6 + FileClose $9 + StrCmp $5 '' +2 + IntCmp $R6 $5 0 FileFunc_GetSize_findnext + StrCmp $6 '' +2 + IntCmp $R6 $6 0 0 FileFunc_GetSize_findnext + IntOp $R4 $R4 + 1 + System::Int64Op $R3 + $R6 + Pop $R3 + + FileFunc_GetSize_findnext: + FindNext $0 $R7 + IfErrors 0 FileFunc_GetSize_dir + FindClose $0 + + FileFunc_GetSize_show: + StrCmp $5$6 '' FileFunc_GetSize_nosize + System::Int64Op $R3 / $1 + Pop $9 + DetailPrint 'Size:$9 $2 Files:$R4 Folders:$R5' + goto FileFunc_GetSize_subdir + FileFunc_GetSize_nosize: + DetailPrint 'Files:$R4 Folders:$R5' + + FileFunc_GetSize_subdir: + StrCmp $7 0 FileFunc_GetSize_preend + FindFirst $0 $R7 '$R8\*.*' + StrCmp $R7 '.' 0 FileFunc_GetSize_pushdir + FindNext $0 $R7 + StrCmp $R7 '..' 0 FileFunc_GetSize_pushdir + FindNext $0 $R7 + IfErrors 0 FileFunc_GetSize_pushdir + FindClose $0 + StrCmp $8 0 FileFunc_GetSize_preend FileFunc_GetSize_nextdir + + FileFunc_GetSize_pushdir: + IfFileExists '$R8\$R7\*.*' 0 +3 + Push '$R8\$R7' + IntOp $8 $8 + 1 + FindNext $0 $R7 + IfErrors 0 FileFunc_GetSize_pushdir + FindClose $0 + StrCmp $8 0 FileFunc_GetSize_preend FileFunc_GetSize_nextdir + + FileFunc_GetSize_preend: + StrCmp $R3 '' FileFunc_GetSize_nosizeend + System::Int64Op $R3 / $1 + Pop $R3 + FileFunc_GetSize_nosizeend: + StrCpy $2 $R4 + StrCpy $1 $R5 + StrCpy $0 $R3 + goto FileFunc_GetSize_end + + FileFunc_GetSize_error: + SetErrors + StrCpy $0 '' + StrCpy $1 '' + StrCpy $2 '' + + FileFunc_GetSize_end: + SetDetailsPrint both + Pop $R9 + Pop $R8 + Pop $R7 + Pop $R6 + Pop $R5 + Pop $R4 + Pop $R3 + Pop $9 + Pop $8 + Pop $7 + Pop $6 + Pop $5 + Pop $4 + Pop $3 + Exch $2 + Exch + Exch $1 + Exch 2 + Exch $0 + + !verbose pop +!macroend + +!define DriveSpace `!insertmacro DriveSpaceCall` +!define un.DriveSpace `!insertmacro DriveSpaceCall` + +!macro DriveSpace +!macroend + +!macro un.DriveSpace +!macroend + +!macro DriveSpace_ + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + + Exch $1 + Exch + Exch $0 + Exch + Push $2 + Push $3 + Push $4 + Push $5 + Push $6 + ClearErrors + + StrCpy $2 $0 1 -1 + StrCmp $2 '\' 0 +3 + StrCpy $0 $0 -1 + goto -3 + IfFileExists '$0\NUL' 0 FileFunc_DriveSpace_error + + StrCpy $5 '' + StrCpy $6 '' + + FileFunc_DriveSpace_option: + StrCpy $2 $1 1 + StrCpy $1 $1 '' 1 + StrCmp $2 ' ' -2 + StrCmp $2 '' FileFunc_DriveSpace_default + StrCmp $2 '/' 0 -4 + StrCpy $3 -1 + IntOp $3 $3 + 1 + StrCpy $2 $1 1 $3 + StrCmp $2 '' +2 + StrCmp $2 '/' 0 -3 + StrCpy $4 $1 $3 + StrCpy $4 $4 '' 2 + StrCpy $2 $4 1 -1 + StrCmp $2 ' ' 0 +3 + StrCpy $4 $4 -1 + goto -3 + StrCpy $2 $1 2 + StrCpy $1 $1 '' $3 + + StrCmp $2 'D=' 0 FileFunc_DriveSpace_unit + StrCpy $5 $4 + StrCmp $5 '' +4 + StrCmp $5 'T' +3 + StrCmp $5 'O' +2 + StrCmp $5 'F' 0 FileFunc_DriveSpace_error + goto FileFunc_DriveSpace_option + + FileFunc_DriveSpace_unit: + StrCmp $2 'S=' 0 FileFunc_DriveSpace_error + StrCpy $6 $4 + goto FileFunc_DriveSpace_option + + FileFunc_DriveSpace_default: + StrCmp $5 '' 0 +2 + StrCpy $5 'T' + StrCmp $6 '' 0 +3 + StrCpy $6 '1' + goto FileFunc_DriveSpace_getspace + + StrCmp $6 'B' 0 +3 + StrCpy $6 1 + goto FileFunc_DriveSpace_getspace + StrCmp $6 'K' 0 +3 + StrCpy $6 1024 + goto FileFunc_DriveSpace_getspace + StrCmp $6 'M' 0 +3 + StrCpy $6 1048576 + goto FileFunc_DriveSpace_getspace + StrCmp $6 'G' 0 FileFunc_DriveSpace_error + StrCpy $6 1073741824 + + FileFunc_DriveSpace_getspace: + System::Call 'kernel32::GetDiskFreeSpaceEx(t, *l, *l, *l)i(r0,.r2,.r3,.)' + + StrCmp $5 T 0 +3 + StrCpy $0 $3 + goto FileFunc_DriveSpace_getsize + StrCmp $5 O 0 +4 + System::Int64Op $3 - $2 + Pop $0 + goto FileFunc_DriveSpace_getsize + StrCmp $5 F 0 +2 + StrCpy $0 $2 + + FileFunc_DriveSpace_getsize: + System::Int64Op $0 / $6 + Pop $0 + goto FileFunc_DriveSpace_end + + FileFunc_DriveSpace_error: + SetErrors + StrCpy $0 '' + + FileFunc_DriveSpace_end: + Pop $6 + Pop $5 + Pop $4 + Pop $3 + Pop $2 + Pop $1 + Exch $0 + + !verbose pop +!macroend + +!define GetDrives `!insertmacro GetDrivesCall` +!define un.GetDrives `!insertmacro GetDrivesCall` + +!macro GetDrives +!macroend + +!macro un.GetDrives +!macroend + +!macro GetDrives_ + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + + Exch $1 + Exch + Exch $0 + Exch + Push $2 + Push $3 + Push $4 + Push $5 + Push $6 + Push $8 + Push $9 + + System::StrAlloc 1024 + Pop $2 + System::Call 'kernel32::GetLogicalDriveStrings(i,i) i(1024, r2)' + + StrCmp $0 ALL FileFunc_GetDrives_drivestring + StrCmp $0 '' 0 FileFunc_GetDrives_typeset + StrCpy $0 ALL + goto FileFunc_GetDrives_drivestring + + FileFunc_GetDrives_typeset: + StrCpy $6 -1 + IntOp $6 $6 + 1 + StrCpy $8 $0 1 $6 + StrCmp $8$0 '' FileFunc_GetDrives_enumex + StrCmp $8 '' +2 + StrCmp $8 '+' 0 -4 + StrCpy $8 $0 $6 + IntOp $6 $6 + 1 + StrCpy $0 $0 '' $6 + + StrCmp $8 'FDD' 0 +3 + StrCpy $6 2 + goto FileFunc_GetDrives_drivestring + StrCmp $8 'HDD' 0 +3 + StrCpy $6 3 + goto FileFunc_GetDrives_drivestring + StrCmp $8 'NET' 0 +3 + StrCpy $6 4 + goto FileFunc_GetDrives_drivestring + StrCmp $8 'CDROM' 0 +3 + StrCpy $6 5 + goto FileFunc_GetDrives_drivestring + StrCmp $8 'RAM' 0 FileFunc_GetDrives_typeset + StrCpy $6 6 + + FileFunc_GetDrives_drivestring: + StrCpy $3 $2 + + FileFunc_GetDrives_enumok: + System::Call 'kernel32::lstrlen(t) i(i r3) .r4' + StrCmp $4$0 '0ALL' FileFunc_GetDrives_enumex + StrCmp $4 0 FileFunc_GetDrives_typeset + System::Call 'kernel32::GetDriveType(t) i(i r3) .r5' + + StrCmp $0 ALL +2 + StrCmp $5 $6 FileFunc_GetDrives_letter FileFunc_GetDrives_enumnext + StrCmp $5 2 0 +3 + StrCpy $8 FDD + goto FileFunc_GetDrives_letter + StrCmp $5 3 0 +3 + StrCpy $8 HDD + goto FileFunc_GetDrives_letter + StrCmp $5 4 0 +3 + StrCpy $8 NET + goto FileFunc_GetDrives_letter + StrCmp $5 5 0 +3 + StrCpy $8 CDROM + goto FileFunc_GetDrives_letter + StrCmp $5 6 0 FileFunc_GetDrives_enumex + StrCpy $8 RAM + + FileFunc_GetDrives_letter: + System::Call '*$3(&t1024 .r9)' + + Push $0 + Push $1 + Push $2 + Push $3 + Push $4 + Push $5 + Push $6 + Push $8 + Call $1 + Pop $9 + Pop $8 + Pop $6 + Pop $5 + Pop $4 + Pop $3 + Pop $2 + Pop $1 + Pop $0 + StrCmp $9 'StopGetDrives' FileFunc_GetDrives_enumex + + FileFunc_GetDrives_enumnext: + IntOp $4 $4 * ${NSIS_CHAR_SIZE} + IntOp $3 $3 + $4 + IntOp $3 $3 + ${NSIS_CHAR_SIZE} + goto FileFunc_GetDrives_enumok + + FileFunc_GetDrives_enumex: + System::Free $2 + + Pop $9 + Pop $8 + Pop $6 + Pop $5 + Pop $4 + Pop $3 + Pop $2 + Pop $1 + Pop $0 + + !verbose pop +!macroend + +!define GetTime `!insertmacro GetTimeCall` +!define un.GetTime `!insertmacro GetTimeCall` + +!macro GetTime +!macroend + +!macro un.GetTime +!macroend + +!macro GetTime_ + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + + Exch $1 + Exch + Exch $0 + Exch + Push $2 + Push $3 + Push $4 + Push $5 + Push $6 + Push $7 + ClearErrors + + StrCmp $1 'L' FileFunc_GetTime_gettime + StrCmp $1 'A' FileFunc_GetTime_getfile + StrCmp $1 'C' FileFunc_GetTime_getfile + StrCmp $1 'M' FileFunc_GetTime_getfile + StrCmp $1 'LS' FileFunc_GetTime_gettime + StrCmp $1 'AS' FileFunc_GetTime_getfile + StrCmp $1 'CS' FileFunc_GetTime_getfile + StrCmp $1 'MS' FileFunc_GetTime_getfile + goto FileFunc_GetTime_error + + FileFunc_GetTime_getfile: + IfFileExists $0 0 FileFunc_GetTime_error + System::Call '*(i,l,l,l,i,i,i,i,&t260,&t14) p .r6' + System::Call 'kernel32::FindFirstFile(t,p)p(r0,r6) .r2' + System::Call 'kernel32::FindClose(i)i(r2)' + + FileFunc_GetTime_gettime: + System::Call '*(&i2,&i2,&i2,&i2,&i2,&i2,&i2,&i2) p .r7' + StrCmp $1 'L' 0 FileFunc_GetTime_systemtime + System::Call 'kernel32::GetLocalTime(p)i(r7)' + goto FileFunc_GetTime_convert + FileFunc_GetTime_systemtime: + StrCmp $1 'LS' 0 FileFunc_GetTime_filetime + System::Call 'kernel32::GetSystemTime(p)i(r7)' + goto FileFunc_GetTime_convert + + FileFunc_GetTime_filetime: + System::Call '*$6(i,l,l,l,i,i,i,i,&t260,&t14)p(,.r4,.r3,.r2)' + System::Free $6 + StrCmp $1 'A' 0 +3 + StrCpy $2 $3 + goto FileFunc_GetTime_tolocal + StrCmp $1 'C' 0 +3 + StrCpy $2 $4 + goto FileFunc_GetTime_tolocal + StrCmp $1 'M' FileFunc_GetTime_tolocal + + StrCmp $1 'AS' FileFunc_GetTime_tosystem + StrCmp $1 'CS' 0 +3 + StrCpy $3 $4 + goto FileFunc_GetTime_tosystem + StrCmp $1 'MS' 0 +3 + StrCpy $3 $2 + goto FileFunc_GetTime_tosystem + + FileFunc_GetTime_tolocal: + System::Call 'kernel32::FileTimeToLocalFileTime(*l,*l)i(r2,.r3)' + FileFunc_GetTime_tosystem: + System::Call 'kernel32::FileTimeToSystemTime(*l,i)i(r3,r7)' + + FileFunc_GetTime_convert: + System::Call '*$7(&i2.r5,&i2.r6,&i2.r4,&i2.r0,&i2.r3,&i2.r2,&i2.r1,&i2)' + System::Free $7 + + IntFmt $6 "%.2u" $6 ; Month + IntFmt $0 "%.2u" $0 ; Day + IntFmt $3 "%.2u" $3 ; Hour + IntFmt $2 "%.2u" $2 ; Minute + IntFmt $1 "%.2u" $1 ; Second + + StrCmp $4 0 0 +3 + StrCpy $4 Sunday + goto FileFunc_GetTime_end + StrCmp $4 1 0 +3 + StrCpy $4 Monday + goto FileFunc_GetTime_end + StrCmp $4 2 0 +3 + StrCpy $4 Tuesday + goto FileFunc_GetTime_end + StrCmp $4 3 0 +3 + StrCpy $4 Wednesday + goto FileFunc_GetTime_end + StrCmp $4 4 0 +3 + StrCpy $4 Thursday + goto FileFunc_GetTime_end + StrCmp $4 5 0 +3 + StrCpy $4 Friday + goto FileFunc_GetTime_end + StrCmp $4 6 0 FileFunc_GetTime_error + StrCpy $4 Saturday + goto FileFunc_GetTime_end + + FileFunc_GetTime_error: + SetErrors + StrCpy $0 '' + StrCpy $1 '' + StrCpy $2 '' + StrCpy $3 '' + StrCpy $4 '' + StrCpy $5 '' + StrCpy $6 '' + + FileFunc_GetTime_end: + Pop $7 + Exch $6 + Exch + Exch $5 + Exch 2 + Exch $4 + Exch 3 + Exch $3 + Exch 4 + Exch $2 + Exch 5 + Exch $1 + Exch 6 + Exch $0 + + !verbose pop +!macroend + +!define GetFileAttributes `!insertmacro GetFileAttributesCall` +!define un.GetFileAttributes `!insertmacro GetFileAttributesCall` + +!macro GetFileAttributes +!macroend + +!macro un.GetFileAttributes +!macroend + +!macro GetFileAttributes_ + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + + Exch $1 + Exch + Exch $0 + Exch + Push $2 + Push $3 + Push $4 + Push $5 + + System::Call 'kernel32::GetFileAttributes(t r0)i .r2' + StrCmp $2 -1 FileFunc_GetFileAttributes_error + StrCpy $3 '' + + IntOp $0 $2 & 0x4000 + IntCmp $0 0 +2 + StrCpy $3 'ENCRYPTED|' + + IntOp $0 $2 & 0x2000 + IntCmp $0 0 +2 + StrCpy $3 'NOT_CONTENT_INDEXED|$3' + + IntOp $0 $2 & 0x1000 + IntCmp $0 0 +2 + StrCpy $3 'OFFLINE|$3' + + IntOp $0 $2 & 0x0800 + IntCmp $0 0 +2 + StrCpy $3 'COMPRESSED|$3' + + IntOp $0 $2 & 0x0400 + IntCmp $0 0 +2 + StrCpy $3 'REPARSE_POINT|$3' + + IntOp $0 $2 & 0x0200 + IntCmp $0 0 +2 + StrCpy $3 'SPARSE_FILE|$3' + + IntOp $0 $2 & 0x0100 + IntCmp $0 0 +2 + StrCpy $3 'TEMPORARY|$3' + + IntOp $0 $2 & 0x0080 + IntCmp $0 0 +2 + StrCpy $3 'NORMAL|$3' + + IntOp $0 $2 & 0x0040 + IntCmp $0 0 +2 + StrCpy $3 'DEVICE|$3' + + IntOp $0 $2 & 0x0020 + IntCmp $0 0 +2 + StrCpy $3 'ARCHIVE|$3' + + IntOp $0 $2 & 0x0010 + IntCmp $0 0 +2 + StrCpy $3 'DIRECTORY|$3' + + IntOp $0 $2 & 0x0004 + IntCmp $0 0 +2 + StrCpy $3 'SYSTEM|$3' + + IntOp $0 $2 & 0x0002 + IntCmp $0 0 +2 + StrCpy $3 'HIDDEN|$3' + + IntOp $0 $2 & 0x0001 + IntCmp $0 0 +2 + StrCpy $3 'READONLY|$3' + + StrCpy $0 $3 -1 + StrCmp $1 '' FileFunc_GetFileAttributes_end + StrCmp $1 'ALL' FileFunc_GetFileAttributes_end + + FileFunc_GetFileAttributes_attrcmp: + StrCpy $5 0 + IntOp $5 $5 + 1 + StrCpy $4 $1 1 $5 + StrCmp $4 '' +2 + StrCmp $4 '|' 0 -3 + StrCpy $2 $1 $5 + IntOp $5 $5 + 1 + StrCpy $1 $1 '' $5 + StrLen $3 $2 + StrCpy $5 -1 + IntOp $5 $5 + 1 + StrCpy $4 $0 $3 $5 + StrCmp $4 '' FileFunc_GetFileAttributes_notfound + StrCmp $4 $2 0 -3 + StrCmp $1 '' 0 FileFunc_GetFileAttributes_attrcmp + StrCpy $0 1 + goto FileFunc_GetFileAttributes_end + + FileFunc_GetFileAttributes_notfound: + StrCpy $0 0 + goto FileFunc_GetFileAttributes_end + + FileFunc_GetFileAttributes_error: + SetErrors + StrCpy $0 '' + + FileFunc_GetFileAttributes_end: + Pop $5 + Pop $4 + Pop $3 + Pop $2 + Pop $1 + Exch $0 + + !verbose pop +!macroend + +!define GetFileVersion `!insertmacro GetFileVersionCall` +!define un.GetFileVersion `!insertmacro GetFileVersionCall` + +!macro GetFileVersion +!macroend + +!macro un.GetFileVersion +!macroend + +!macro GetFileVersion_ + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + + Exch $0 + Push $1 + Push $2 + Push $3 + Push $4 + Push $5 + Push $6 + ClearErrors + + GetDllVersion '$0' $1 $2 + IfErrors FileFunc_GetFileVersion_error + IntOp $3 $1 >> 16 + IntOp $3 $3 & 0x0000FFFF + IntOp $4 $1 & 0x0000FFFF + IntOp $5 $2 >> 16 + IntOp $5 $5 & 0x0000FFFF + IntOp $6 $2 & 0x0000FFFF + StrCpy $0 '$3.$4.$5.$6' + goto FileFunc_GetFileVersion_end + + FileFunc_GetFileVersion_error: + SetErrors + StrCpy $0 '' + + FileFunc_GetFileVersion_end: + Pop $6 + Pop $5 + Pop $4 + Pop $3 + Pop $2 + Pop $1 + Exch $0 + + !verbose pop +!macroend + +!define GetExeName `!insertmacro GetExeNameCall` +!define un.GetExeName `!insertmacro GetExeNameCall` + +!macro GetExeName +!macroend + +!macro un.GetExeName +!macroend + +!macro GetExeName_ + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + + Push $0 + Push $1 + Push $2 + System::Call 'kernel32::GetModuleFileName(p 0, t.r0, i ${NSIS_MAX_STRLEN})' + System::Call 'kernel32::GetLongPathName(t r0, t.r1, i ${NSIS_MAX_STRLEN})i.r2' + StrCmp $2 error +2 + StrCpy $0 $1 + Pop $2 + Pop $1 + Exch $0 + + !verbose pop +!macroend + +!define GetExePath `!insertmacro GetExePathCall` +!define un.GetExePath `!insertmacro GetExePathCall` + +!macro GetExePath +!macroend + +!macro un.GetExePath +!macroend + +!macro GetExePath_ + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + + Push $0 + Push $1 + Push $2 + StrCpy $0 $EXEDIR + System::Call 'kernel32::GetLongPathName(t r0, t.r1, i ${NSIS_MAX_STRLEN})i.r2' + StrCmp $2 error +2 + StrCpy $0 $1 + Pop $2 + Pop $1 + Exch $0 + + !verbose pop +!macroend + +!define GetParameters `!insertmacro GetParametersCall` +!define un.GetParameters `!insertmacro GetParametersCall` + +!macro GetParameters +!macroend + +!macro un.GetParameters +!macroend + +!macro GetParameters_ + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + + ;cmdline-check + StrCmp $CMDLINE "" 0 +3 + Push "" + Return + + ;vars + Push $0 ;tmp + Push $1 ;length + Push $2 ;parameter offset + Push $3 ;separator + + ;length/offset + StrLen $1 $CMDLINE + StrCpy $2 2 ;start with third character + + ;separator + StrCpy $3 $CMDLINE 1 ;first character + StrCmp $3 '"' +2 + StrCpy $3 ' ' + + FileFunc_GetParameters_token: ;finding second separator + IntCmp $2 $1 FileFunc_GetParameters_strip 0 FileFunc_GetParameters_strip + StrCpy $0 $CMDLINE 1 $2 + IntOp $2 $2 + 1 + StrCmp $3 $0 0 FileFunc_GetParameters_token + + FileFunc_GetParameters_strip: ;strip white space + IntCmp $2 $1 FileFunc_GetParameters_copy 0 FileFunc_GetParameters_copy + StrCpy $0 $CMDLINE 1 $2 + StrCmp $0 ' ' 0 FileFunc_GetParameters_copy + IntOp $2 $2 + 1 + Goto FileFunc_GetParameters_strip + + FileFunc_GetParameters_copy: + StrCpy $0 $CMDLINE "" $2 + + ;strip white spaces from end + FileFunc_GetParameters_rstrip: + StrCpy $1 $0 1 -1 + StrCmp $1 ' ' 0 FileFunc_GetParameters_done + StrCpy $0 $0 -1 + Goto FileFunc_GetParameters_rstrip + + FileFunc_GetParameters_done: + Pop $3 + Pop $2 + Pop $1 + Exch $0 + + !verbose pop +!macroend + +!macro GetOptionsBody _FILEFUNC_S + + Exch $1 + Exch + Exch $0 + Exch + Push $2 + Push $3 + Push $4 + Push $5 + Push $6 + Push $7 + ClearErrors + + StrCpy $2 $1 '' 1 + StrCpy $1 $1 1 + StrLen $3 $2 + StrCpy $7 0 + + FileFunc_GetOptions${_FILEFUNC_S}_begin: + StrCpy $4 -1 + StrCpy $6 '' + + FileFunc_GetOptions${_FILEFUNC_S}_quote: + IntOp $4 $4 + 1 + StrCpy $5 $0 1 $4 + StrCmp${_FILEFUNC_S} $5$7 '0' FileFunc_GetOptions${_FILEFUNC_S}_notfound + StrCmp${_FILEFUNC_S} $5 '' FileFunc_GetOptions${_FILEFUNC_S}_trimright + StrCmp${_FILEFUNC_S} $5 '"' 0 +7 + StrCmp${_FILEFUNC_S} $6 '' 0 +3 + StrCpy $6 '"' + goto FileFunc_GetOptions${_FILEFUNC_S}_quote + StrCmp${_FILEFUNC_S} $6 '"' 0 +3 + StrCpy $6 '' + goto FileFunc_GetOptions${_FILEFUNC_S}_quote + StrCmp${_FILEFUNC_S} $5 `'` 0 +7 + StrCmp${_FILEFUNC_S} $6 `` 0 +3 + StrCpy $6 `'` + goto FileFunc_GetOptions${_FILEFUNC_S}_quote + StrCmp${_FILEFUNC_S} $6 `'` 0 +3 + StrCpy $6 `` + goto FileFunc_GetOptions${_FILEFUNC_S}_quote + StrCmp${_FILEFUNC_S} $5 '`' 0 +7 + StrCmp${_FILEFUNC_S} $6 '' 0 +3 + StrCpy $6 '`' + goto FileFunc_GetOptions${_FILEFUNC_S}_quote + StrCmp${_FILEFUNC_S} $6 '`' 0 +3 + StrCpy $6 '' + goto FileFunc_GetOptions${_FILEFUNC_S}_quote + StrCmp${_FILEFUNC_S} $6 '"' FileFunc_GetOptions${_FILEFUNC_S}_quote + StrCmp${_FILEFUNC_S} $6 `'` FileFunc_GetOptions${_FILEFUNC_S}_quote + StrCmp${_FILEFUNC_S} $6 '`' FileFunc_GetOptions${_FILEFUNC_S}_quote + StrCmp${_FILEFUNC_S} $5 $1 0 FileFunc_GetOptions${_FILEFUNC_S}_quote + StrCmp${_FILEFUNC_S} $7 0 FileFunc_GetOptions${_FILEFUNC_S}_trimleft FileFunc_GetOptions${_FILEFUNC_S}_trimright + + FileFunc_GetOptions${_FILEFUNC_S}_trimleft: + IntOp $4 $4 + 1 + StrCpy $5 $0 $3 $4 + StrCmp${_FILEFUNC_S} $5 '' FileFunc_GetOptions${_FILEFUNC_S}_notfound + StrCmp${_FILEFUNC_S} $5 $2 0 FileFunc_GetOptions${_FILEFUNC_S}_quote + IntOp $4 $4 + $3 + StrCpy $0 $0 '' $4 + StrCpy $4 $0 1 + StrCmp${_FILEFUNC_S} $4 ' ' 0 +3 + StrCpy $0 $0 '' 1 + goto -3 + StrCpy $7 1 + goto FileFunc_GetOptions${_FILEFUNC_S}_begin + + FileFunc_GetOptions${_FILEFUNC_S}_trimright: + StrCpy $0 $0 $4 + StrCpy $4 $0 1 -1 + StrCmp${_FILEFUNC_S} $4 ' ' 0 +3 + StrCpy $0 $0 -1 + goto -3 + StrCpy $3 $0 1 + StrCpy $4 $0 1 -1 + StrCmp${_FILEFUNC_S} $3 $4 0 FileFunc_GetOptions${_FILEFUNC_S}_end + StrCmp${_FILEFUNC_S} $3 '"' +3 + StrCmp${_FILEFUNC_S} $3 `'` +2 + StrCmp${_FILEFUNC_S} $3 '`' 0 FileFunc_GetOptions${_FILEFUNC_S}_end + StrCpy $0 $0 -1 1 + goto FileFunc_GetOptions${_FILEFUNC_S}_end + + FileFunc_GetOptions${_FILEFUNC_S}_notfound: + SetErrors + StrCpy $0 '' + + FileFunc_GetOptions${_FILEFUNC_S}_end: + Pop $7 + Pop $6 + Pop $5 + Pop $4 + Pop $3 + Pop $2 + Pop $1 + Exch $0 + +!macroend + +!define GetOptions `!insertmacro GetOptionsCall` +!define un.GetOptions `!insertmacro GetOptionsCall` + +!macro GetOptions +!macroend + +!macro un.GetOptions +!macroend + +!macro GetOptions_ + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + + !insertmacro GetOptionsBody '' + + !verbose pop +!macroend + +!define GetOptionsS `!insertmacro GetOptionsSCall` +!define un.GetOptionsS `!insertmacro GetOptionsSCall` + +!macro GetOptionsS +!macroend + +!macro un.GetOptionsS +!macroend + +!macro GetOptionsS_ + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + + !insertmacro GetOptionsBody 'S' + + !verbose pop +!macroend + +!define GetRoot `!insertmacro GetRootCall` +!define un.GetRoot `!insertmacro GetRootCall` + +!macro GetRoot +!macroend + +!macro un.GetRoot +!macroend + +!macro GetRoot_ + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + + Exch $0 + Push $1 + Push $2 + Push $3 + + StrCpy $1 $0 2 + StrCmp $1 '\\' FileFunc_GetRoot_UNC + StrCpy $2 $1 1 1 + StrCmp $2 ':' 0 FileFunc_GetRoot_empty + StrCpy $0 $1 + goto FileFunc_GetRoot_end + + FileFunc_GetRoot_UNC: + StrCpy $2 1 + StrCpy $3 '' + + FileFunc_GetRoot_loop: + IntOp $2 $2 + 1 + StrCpy $1 $0 1 $2 + StrCmp $1$3 '' FileFunc_GetRoot_empty + StrCmp $1 '' +5 + StrCmp $1 '\' 0 FileFunc_GetRoot_loop + StrCmp $3 '1' +3 + StrCpy $3 '1' + goto FileFunc_GetRoot_loop + StrCpy $0 $0 $2 + StrCpy $2 $0 1 -1 + StrCmp $2 '\' 0 FileFunc_GetRoot_end + + FileFunc_GetRoot_empty: + StrCpy $0 '' + + FileFunc_GetRoot_end: + Pop $3 + Pop $2 + Pop $1 + Exch $0 + + !verbose pop +!macroend + +!define GetParent `!insertmacro GetParentCall` +!define un.GetParent `!insertmacro GetParentCall` + +!macro GetParent +!macroend + +!macro un.GetParent +!macroend + +!macro GetParent_ + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + + Exch $0 + Push $1 + Push $2 + + StrCpy $2 $0 1 -1 + StrCmp $2 '\' 0 +3 + StrCpy $0 $0 -1 + goto -3 + + StrCpy $1 0 + IntOp $1 $1 - 1 + StrCpy $2 $0 1 $1 + StrCmp $2 '\' +2 + StrCmp $2 '' 0 -3 + StrCpy $0 $0 $1 + + Pop $2 + Pop $1 + Exch $0 + + !verbose pop +!macroend + +!define GetFileName `!insertmacro GetFileNameCall` +!define un.GetFileName `!insertmacro GetFileNameCall` + +!macro GetFileName +!macroend + +!macro un.GetFileName +!macroend + +!macro GetFileName_ + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + + Exch $0 + Push $1 + Push $2 + + StrCpy $2 $0 1 -1 + StrCmp $2 '\' 0 +3 + StrCpy $0 $0 -1 + goto -3 + + StrCpy $1 0 + IntOp $1 $1 - 1 + StrCpy $2 $0 1 $1 + StrCmp $2 '' FileFunc_GetFileName_end + StrCmp $2 '\' 0 -3 + IntOp $1 $1 + 1 + StrCpy $0 $0 '' $1 + + FileFunc_GetFileName_end: + Pop $2 + Pop $1 + Exch $0 + + !verbose pop +!macroend + +!define GetBaseName `!insertmacro GetBaseNameCall` +!define un.GetBaseName `!insertmacro GetBaseNameCall` + +!macro GetBaseName +!macroend + +!macro un.GetBaseName +!macroend + +!macro GetBaseName_ + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + + Exch $0 + Push $1 + Push $2 + Push $3 + + StrCpy $1 0 + StrCpy $3 '' + + FileFunc_GetBaseName_loop: + IntOp $1 $1 - 1 + StrCpy $2 $0 1 $1 + StrCmp $2 '' FileFunc_GetBaseName_trimpath + StrCmp $2 '\' FileFunc_GetBaseName_trimpath + StrCmp $3 'noext' FileFunc_GetBaseName_loop + StrCmp $2 '.' 0 FileFunc_GetBaseName_loop + StrCpy $0 $0 $1 + StrCpy $3 'noext' + StrCpy $1 0 + goto FileFunc_GetBaseName_loop + + FileFunc_GetBaseName_trimpath: + StrCmp $1 -1 FileFunc_GetBaseName_empty + IntOp $1 $1 + 1 + StrCpy $0 $0 '' $1 + goto FileFunc_GetBaseName_end + + FileFunc_GetBaseName_empty: + StrCpy $0 '' + + FileFunc_GetBaseName_end: + Pop $3 + Pop $2 + Pop $1 + Exch $0 + + !verbose pop +!macroend + +!define GetFileExt `!insertmacro GetFileExtCall` +!define un.GetFileExt `!insertmacro GetFileExtCall` + +!macro GetFileExt +!macroend + +!macro un.GetFileExt +!macroend + +!macro GetFileExt_ + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + + Exch $0 + Push $1 + Push $2 + + StrCpy $1 0 + + FileFunc_GetFileExt_loop: + IntOp $1 $1 - 1 + StrCpy $2 $0 1 $1 + StrCmp $2 '' FileFunc_GetFileExt_empty + StrCmp $2 '\' FileFunc_GetFileExt_empty + StrCmp $2 '.' 0 FileFunc_GetFileExt_loop + + StrCmp $1 -1 FileFunc_GetFileExt_empty + IntOp $1 $1 + 1 + StrCpy $0 $0 '' $1 + goto FileFunc_GetFileExt_end + + FileFunc_GetFileExt_empty: + StrCpy $0 '' + + FileFunc_GetFileExt_end: + Pop $2 + Pop $1 + Exch $0 + + !verbose pop +!macroend + +!define BannerTrimPath `!insertmacro BannerTrimPathCall` +!define un.BannerTrimPath `!insertmacro BannerTrimPathCall` + +!macro BannerTrimPath +!macroend + +!macro un.BannerTrimPath +!macroend + +!macro BannerTrimPath_ + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + + Exch $1 + Exch + Exch $0 + Exch + Push $2 + Push $3 + Push $4 + + StrCpy $3 $1 1 -1 + IntOp $1 $1 + 0 + StrLen $2 $0 + IntCmp $2 $1 FileFunc_BannerTrimPath_end FileFunc_BannerTrimPath_end + IntOp $1 $1 - 3 + IntCmp $1 0 FileFunc_BannerTrimPath_empty FileFunc_BannerTrimPath_empty + StrCmp $3 'A' FileFunc_BannerTrimPath_A-trim + StrCmp $3 'B' FileFunc_BannerTrimPath_B-trim + StrCmp $3 'C' FileFunc_BannerTrimPath_C-trim + StrCmp $3 'D' FileFunc_BannerTrimPath_D-trim + + FileFunc_BannerTrimPath_A-trim: + StrCpy $3 $0 1 1 + StrCpy $2 0 + StrCmp $3 ':' 0 +2 + IntOp $2 $2 + 2 + + FileFunc_BannerTrimPath_loopleft: + IntOp $2 $2 + 1 + StrCpy $3 $0 1 $2 + StrCmp $2 $1 FileFunc_BannerTrimPath_C-trim + StrCmp $3 '\' 0 FileFunc_BannerTrimPath_loopleft + StrCpy $3 $0 $2 + IntOp $2 $2 - $1 + IntCmp $2 0 FileFunc_BannerTrimPath_B-trim 0 FileFunc_BannerTrimPath_B-trim + + FileFunc_BannerTrimPath_loopright: + IntOp $2 $2 + 1 + StrCpy $4 $0 1 $2 + StrCmp $2 0 FileFunc_BannerTrimPath_B-trim + StrCmp $4 '\' 0 FileFunc_BannerTrimPath_loopright + StrCpy $4 $0 '' $2 + StrCpy $0 '$3\...$4' + goto FileFunc_BannerTrimPath_end + + FileFunc_BannerTrimPath_B-trim: + StrCpy $2 $1 + IntOp $2 $2 - 1 + StrCmp $2 -1 FileFunc_BannerTrimPath_C-trim + StrCpy $3 $0 1 $2 + StrCmp $3 '\' 0 -3 + StrCpy $0 $0 $2 + StrCpy $0 '$0\...' + goto FileFunc_BannerTrimPath_end + + FileFunc_BannerTrimPath_C-trim: + StrCpy $0 $0 $1 + StrCpy $0 '$0...' + goto FileFunc_BannerTrimPath_end + + FileFunc_BannerTrimPath_D-trim: + StrCpy $3 -1 + IntOp $3 $3 - 1 + StrCmp $3 -$2 FileFunc_BannerTrimPath_C-trim + StrCpy $4 $0 1 $3 + StrCmp $4 '\' 0 -3 + StrCpy $4 $0 '' $3 + IntOp $3 $1 + $3 + IntCmp $3 2 FileFunc_BannerTrimPath_C-trim FileFunc_BannerTrimPath_C-trim + StrCpy $0 $0 $3 + StrCpy $0 '$0...$4' + goto FileFunc_BannerTrimPath_end + + FileFunc_BannerTrimPath_empty: + StrCpy $0 '' + + FileFunc_BannerTrimPath_end: + Pop $4 + Pop $3 + Pop $2 + Pop $1 + Exch $0 + + !verbose pop +!macroend + +!define DirState `!insertmacro DirStateCall` +!define un.DirState `!insertmacro DirStateCall` + +!macro DirState +!macroend + +!macro un.DirState +!macroend + +!macro DirState_ + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + + Exch $0 + Push $1 + ClearErrors + + FindFirst $1 $0 '$0\*.*' + IfErrors 0 +3 + StrCpy $0 -1 + goto FileFunc_DirState_end + StrCmp $0 '.' 0 +4 + FindNext $1 $0 + StrCmp $0 '..' 0 +2 + FindNext $1 $0 + FindClose $1 + IfErrors 0 +3 + StrCpy $0 0 + goto FileFunc_DirState_end + StrCpy $0 1 + + FileFunc_DirState_end: + Pop $1 + Exch $0 + + !verbose pop +!macroend + +!define RefreshShellIcons `!insertmacro RefreshShellIconsCall` +!define un.RefreshShellIcons `!insertmacro RefreshShellIconsCall` + +!macro RefreshShellIcons +!macroend + +!macro un.RefreshShellIcons +!macroend + +!macro RefreshShellIcons_ + !verbose push + !verbose ${_FILEFUNC_VERBOSE} + + System::Call 'shell32::SHChangeNotify(i 0x08000000, i 0, i 0, i 0)' + + !verbose pop +!macroend + +!verbose pop +!endif diff --git a/installer/tools/Include/x64.nsh b/installer/tools/Include/x64.nsh new file mode 100644 index 00000000..59d9e8c2 --- /dev/null +++ b/installer/tools/Include/x64.nsh @@ -0,0 +1,120 @@ +; --------------------- +; x64.nsh +; --------------------- +; +; A few simple macros to handle installations on x64 machines. +; +; RunningX64 checks if the installer is running on a 64-bit OS. +; IsWow64 checks if the installer is a 32-bit application running on a 64-bit OS. +; +; ${If} ${RunningX64} +; MessageBox MB_OK "Running on 64-bit Windows" +; ${EndIf} +; +; IsNative* checks the OS native CPU architecture. +; +; ${If} ${IsNativeAMD64} +; ; Install AMD64 64-bit driver/library +; ${ElseIf} ${IsNativeARM64} +; ; Install ARM64 64-bit driver/library +; ${ElseIf} ${IsNativeIA32} +; ; Install i386 32-bit driver/library +; ${Else} +; Abort "Unsupported CPU architecture!" +; ${EndIf} +; +; ${If} ${IsNativeAMD64} +; File "amd64\myapp.exe" +; ${ElseIf} ${IsNativeIA32} +; ${OrIf} ${IsWow64} +; File "x86\myapp.exe" +; ${Else} +; Abort "Unsupported CPU architecture!" +; ${EndIf} +; +; DisableX64FSRedirection disables file system redirection. +; EnableX64FSRedirection enables file system redirection. +; +; SetOutPath $SYSDIR +; ${DisableX64FSRedirection} +; File something.bin # extracts to C:\Windows\System32 +; ${EnableX64FSRedirection} +; File something.bin # extracts to C:\Windows\SysWOW64 +; + +!ifndef ___X64__NSH___ +!define ___X64__NSH___ + +!include LogicLib.nsh + + +!define IsWow64 `"" IsWow64 ""` +!macro _IsWow64 _a _b _t _f + !insertmacro _LOGICLIB_TEMP + System::Call kernel32::GetCurrentProcess()p.s + System::Call kernel32::IsWow64Process2(ps,*i0s,*i) ; [Win10.1511+] 0 if not WOW64 + Push | + System::Call kernel32::IsWow64Process(p-1,*i0s) ; [WinXP+] FALSE for a 32-bit application on ARM64! + System::Int64Op + Pop $_LOGICLIB_TEMP + !insertmacro _!= $_LOGICLIB_TEMP 0 `${_t}` `${_f}` +!macroend + + +!define RunningX64 `"" RunningX64 ""` +!macro _RunningX64 _a _b _t _f + !if ${NSIS_PTR_SIZE} > 4 + !insertmacro LogicLib_JumpToBranch `${_t}` `${_f}` + !else + !insertmacro _IsWow64 `${_a}` `${_b}` `${_t}` `${_f}` + !endif +!macroend + + +!define GetNativeMachineArchitecture "!insertmacro GetNativeMachineArchitecture " +!macro GetNativeMachineArchitecture outvar + !define GetNativeMachineArchitecture_lbl lbl_GNMA_${__COUNTER__} + System::Call kernel32::GetCurrentProcess()p.s + System::Call kernel32::IsWow64Process2(ps,*i,*i0s) + Pop ${outvar} + IntCmp ${outvar} 0 "" ${GetNativeMachineArchitecture_lbl}_done ${GetNativeMachineArchitecture_lbl}_done + !if "${NSIS_PTR_SIZE}" <= 4 + !if "${NSIS_CHAR_SIZE}" <= 1 + System::Call 'USER32::CharNextW(w"")p.s' + Pop ${outvar} + IntPtrCmpU ${outvar} 0 "" ${GetNativeMachineArchitecture_lbl}_oldnt ${GetNativeMachineArchitecture_lbl}_oldnt + StrCpy ${outvar} 332 ; Always IMAGE_FILE_MACHINE_I386 on Win9x + Goto ${GetNativeMachineArchitecture_lbl}_done + ${GetNativeMachineArchitecture_lbl}_oldnt: + !endif + !endif + System::Call '*0x7FFE002E(&i2.s)' + Pop ${outvar} + ${GetNativeMachineArchitecture_lbl}_done: + !undef GetNativeMachineArchitecture_lbl +!macroend + +!macro _IsNativeMachineArchitecture _ignore _arc _t _f + !insertmacro _LOGICLIB_TEMP + ${GetNativeMachineArchitecture} $_LOGICLIB_TEMP + !insertmacro _= $_LOGICLIB_TEMP ${_arc} `${_t}` `${_f}` +!macroend + +!define IsNativeMachineArchitecture `"" IsNativeMachineArchitecture ` +!define IsNativeIA32 '${IsNativeMachineArchitecture} 332' ; Intel x86 +!define IsNativeAMD64 '${IsNativeMachineArchitecture} 34404' ; x86-64/x64 +!define IsNativeARM64 '${IsNativeMachineArchitecture} 43620' + + +!define DisableX64FSRedirection "!insertmacro DisableX64FSRedirection" +!macro DisableX64FSRedirection + System::Call kernel32::Wow64EnableWow64FsRedirection(i0) +!macroend + +!define EnableX64FSRedirection "!insertmacro EnableX64FSRedirection" +!macro EnableX64FSRedirection + System::Call kernel32::Wow64EnableWow64FsRedirection(i1) +!macroend + + +!endif # !___X64__NSH___ diff --git a/installer/tools/Stubs/lzma_solid-x86-unicode b/installer/tools/Stubs/lzma_solid-x86-unicode new file mode 100644 index 0000000000000000000000000000000000000000..52f10219ad019b06bbcedd3cb076690beb4156f0 GIT binary patch literal 38912 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

WoXWhdnl#d6<^u*Lr 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