# PATH utilities. Taken from: # https://www.smartmontools.org/browser/trunk/smartmontools/os_win32/installer.nsi?rev=5310#L689 ; os_win32/installer.nsi - smartmontools install NSIS script ; ; Home page of code is: https://www.smartmontools.org ; ; Copyright (C) 2006-22 Christian Franke ; ; SPDX-License-Identifier: GPL-2.0-or-later ;-------------------------------------------------------------------- ; Path functions ; ; Based on example from: ; http://nsis.sourceforge.net/Path_Manipulation ; !include "WinMessages.nsh" ; Registry Entry for system environment (NT4,2000,XP) !define Environ 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' ; AddToPath - Appends dir to system PATH ; (does not work on Win9x/ME) ; ; Usage: ; Push "dir" ; Call AddToPath Function AddToPath Exch $0 Push $1 Push $2 Push $3 Push $4 ; NSIS ReadRegStr returns empty string on string overflow ; Native calls are used here to check actual length of PATH ; $4 = RegOpenKey(HKEY_CURRENT_USER, "Environment", &$3) System::Call "advapi32::RegOpenKey(i 0x80000002, t'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', *i.r3) i.r4" IntCmp $4 0 0 done done ; $4 = RegQueryValueEx($3, "PATH", (DWORD*)0, (DWORD*)0, &$1, ($2=NSIS_MAX_STRLEN, &$2)) ; RegCloseKey($3) System::Call "advapi32::RegQueryValueEx(i $3, t'PATH', i 0, i 0, t.r1, *i ${NSIS_MAX_STRLEN} r2) i.r4" System::Call "advapi32::RegCloseKey(i $3)" ${If} $4 = 234 ; ERROR_MORE_DATA DetailPrint "AddToPath: original length $2 > ${NSIS_MAX_STRLEN}" MessageBox MB_OK "PATH not updated, original length $2 > ${NSIS_MAX_STRLEN}" /SD IDOK Goto done ${EndIf} ${If} $4 <> 0 ; NO_ERROR ${If} $4 <> 2 ; ERROR_FILE_NOT_FOUND DetailPrint "AddToPath: unexpected error code $4" Goto done ${EndIf} StrCpy $1 "" ${EndIf} ; Check if already in PATH Push "$1;" Push "$0;" Call StrStr Pop $2 StrCmp $2 "" 0 done Push "$1;" Push "$0\;" Call StrStr Pop $2 StrCmp $2 "" 0 done ; Prevent NSIS string overflow StrLen $2 $0 StrLen $3 $1 IntOp $2 $2 + $3 IntOp $2 $2 + 2 ; $2 = strlen(dir) + strlen(PATH) + sizeof(";") ${If} $2 > ${NSIS_MAX_STRLEN} DetailPrint "AddToPath: new length $2 > ${NSIS_MAX_STRLEN}" MessageBox MB_OK "PATH not updated, new length $2 > ${NSIS_MAX_STRLEN}." /SD IDOK Goto done ${EndIf} ; Append dir to PATH DetailPrint "Add to PATH: $0" StrCpy $2 $1 1 -1 ${If} $2 == ";" StrCpy $1 $1 -1 ; remove trailing ';' ${EndIf} ${If} $1 != "" ; no leading ';' StrCpy $0 "$1;$0" ${EndIf} WriteRegExpandStr ${Environ} "PATH" $0 SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 done: Pop $4 Pop $3 Pop $2 Pop $1 Pop $0 FunctionEnd ; RemoveFromPath - Removes dir from system PATH ; ; Usage: ; Push "dir" ; Call RemoveFromPath Function un.RemoveFromPath Exch $0 Push $1 Push $2 Push $3 Push $4 Push $5 Push $6 ReadRegStr $1 ${Environ} "PATH" StrCpy $5 $1 1 -1 ${If} $5 != ";" StrCpy $1 "$1;" ; ensure trailing ';' ${EndIf} Push $1 Push "$0;" Call un.StrStr Pop $2 ; pos of our dir StrCmp $2 "" done DetailPrint "Remove from PATH: $0" StrLen $3 "$0;" StrLen $4 $2 StrCpy $5 $1 -$4 ; $5 is now the part before the path to remove StrCpy $6 $2 "" $3 ; $6 is now the part after the path to remove StrCpy $3 "$5$6" StrCpy $5 $3 1 -1 ${If} $5 == ";" StrCpy $3 $3 -1 ; remove trailing ';' ${EndIf} WriteRegExpandStr ${Environ} "PATH" $3 SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 done: Pop $6 Pop $5 Pop $4 Pop $3 Pop $2 Pop $1 Pop $0 FunctionEnd ; StrStr - find substring in a string ; ; Usage: ; Push "this is some string" ; Push "some" ; Call StrStr ; Pop $0 ; "some string" !macro StrStr un Function ${un}StrStr Exch $R1 ; $R1=substring, stack=[old$R1,string,...] Exch ; stack=[string,old$R1,...] Exch $R2 ; $R2=string, stack=[old$R2,old$R1,...] Push $R3 Push $R4 Push $R5 StrLen $R3 $R1 StrCpy $R4 0 ; $R1=substring, $R2=string, $R3=strlen(substring) ; $R4=count, $R5=tmp ${Do} StrCpy $R5 $R2 $R3 $R4 ${IfThen} $R5 == $R1 ${|} ${ExitDo} ${|} ${IfThen} $R5 == "" ${|} ${ExitDo} ${|} IntOp $R4 $R4 + 1 ${Loop} StrCpy $R1 $R2 "" $R4 Pop $R5 Pop $R4 Pop $R3 Pop $R2 Exch $R1 ; $R1=old$R1, stack=[result,...] FunctionEnd !macroend !insertmacro StrStr "" !insertmacro StrStr "un."