]> git.proxmox.com Git - mirror_smartmontools-debian.git/blobdiff - os_win32/installer.nsi
Imported Upstream version 6.4+svn4214
[mirror_smartmontools-debian.git] / os_win32 / installer.nsi
index d06e0859e242ec27299e560e8496945083549651..78ce0145279047fdb7198798eaca9a128d878f23 100644 (file)
@@ -1,7 +1,7 @@
 ;
-; smartmontools install NSIS script
+; os_win32/installer.nsi - smartmontools install NSIS script
 ;
-; Home page of code is: http://smartmontools.sourceforge.net
+; Home page of code is: http://www.smartmontools.org
 ;
 ; Copyright (C) 2006-15 Christian Franke
 ;
@@ -13,7 +13,7 @@
 ; You should have received a copy of the GNU General Public License
 ; (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
 ;
-; $Id: installer.nsi 4072 2015-04-28 20:35:15Z chrfranke $
+; $Id: installer.nsi 4174 2015-11-22 16:19:29Z chrfranke $
 ;
 
 
@@ -36,6 +36,8 @@
 Name "smartmontools"
 OutFile "${OUTFILE}"
 
+RequestExecutionLevel admin
+
 SetCompressor /solid lzma
 
 XPStyle on
@@ -43,7 +45,7 @@ InstallColors /windows
 
 ; Set in .onInit
 ;InstallDir "$PROGRAMFILES\smartmontools"
-;InstallDirRegKey HKLM "Software\smartmontools" "Install_Dir"
+;InstallDirRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\smartmontools" "InstallLocation"
 
 Var EDITOR
 
@@ -56,12 +58,9 @@ Var EDITOR
 LicenseData "${INPDIR}\doc\COPYING.txt"
 
 !include "FileFunc.nsh"
+!include "LogicLib.nsh"
 !include "Sections.nsh"
 
-!insertmacro GetParameters
-!insertmacro GetOptions
-
-RequestExecutionLevel admin
 
 ;--------------------------------------------------------------------
 ; Pages
@@ -81,6 +80,11 @@ UninstPage instfiles
 InstType "Full"
 InstType "Extract files only"
 InstType "Drive menu"
+!ifdef INPDIR64
+InstType "Full (x64)"
+InstType "Extract files only (x64)"
+InstType "Drive menu (x64)"
+!endif
 
 
 ;--------------------------------------------------------------------
@@ -88,8 +92,17 @@ InstType "Drive menu"
 
 !ifdef INPDIR64
   Section "64-bit version" X64_SECTION
+    SectionIn 4 5 6
     ; Handled in Function CheckX64
   SectionEnd
+
+  !define FULL_TYPES "1 4"
+  !define EXTRACT_TYPES  "2 5"
+  !define DRIVEMENU_TYPE     "3 6"
+!else
+  !define FULL_TYPES "1"
+  !define EXTRACT_TYPES  "2"
+  !define DRIVEMENU_TYPE     "3"
 !endif
 
 SectionGroup "!Program files"
@@ -97,14 +110,15 @@ SectionGroup "!Program files"
   !macro FileExe path option
     !ifdef INPDIR64
       ; Use dummy SetOutPath to control archive location of executables
-      StrCmp $X64 "" +5
+      ${If} $X64 != ""
         Goto +2
           SetOutPath "$INSTDIR\bin64"
         File ${option} '${INPDIR64}\${path}'
-      GoTo +4
+      ${Else}
         Goto +2
           SetOutPath "$INSTDIR\bin"
         File ${option} '${INPDIR}\${path}'
+      ${EndIf}
     !else
       File ${option} '${INPDIR}\${path}'
     !endif
@@ -112,7 +126,7 @@ SectionGroup "!Program files"
 
   Section "smartctl" SMARTCTL_SECTION
 
-    SectionIn 1 2
+    SectionIn ${FULL_TYPES} ${EXTRACT_TYPES}
 
     SetOutPath "$INSTDIR\bin"
     !insertmacro FileExe "bin\smartctl.exe" ""
@@ -121,17 +135,18 @@ SectionGroup "!Program files"
 
   Section "smartd" SMARTD_SECTION
 
-    SectionIn 1 2
+    SectionIn ${FULL_TYPES} ${EXTRACT_TYPES}
 
     SetOutPath "$INSTDIR\bin"
 
     ; Stop service ?
     StrCpy $1 ""
-    IfFileExists "$INSTDIR\bin\smartd.exe" 0 nosrv
+    ${If} ${FileExists} "$INSTDIR\bin\smartd.exe"
       ReadRegStr $0 HKLM "System\CurrentControlSet\Services\smartd" "ImagePath"
-      StrCmp $0 "" nosrv
+      ${If} $0 != ""
         ExecWait "net stop smartd" $1
-  nosrv:
+      ${EndIf}
+    ${EndIf}
     !insertmacro FileExe "bin\smartd.exe" ""
 
     IfFileExists "$INSTDIR\bin\smartd.conf" 0 +2
@@ -142,15 +157,16 @@ SectionGroup "!Program files"
     !insertmacro FileExe "bin\wtssendmsg.exe" ""
 
     ; Restart service ?
-    StrCmp $1 "0" 0 +3
+    ${If} $1 == "0"
       MessageBox MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2  "Restart smartd service ?" /SD IDNO IDYES 0 IDNO +2
         ExecWait "net start smartd"
+    ${EndIf}
 
   SectionEnd
 
   Section "smartctl-nc (GSmartControl)" SMARTCTL_NC_SECTION
 
-    SectionIn 1 2
+    SectionIn ${FULL_TYPES} ${EXTRACT_TYPES}
 
     SetOutPath "$INSTDIR\bin"
     !insertmacro FileExe "bin\smartctl-nc.exe" ""
@@ -159,7 +175,7 @@ SectionGroup "!Program files"
 
   Section "drivedb.h (Drive Database)" DRIVEDB_SECTION
 
-    SectionIn 1 2
+    SectionIn ${FULL_TYPES} ${EXTRACT_TYPES}
 
     SetOutPath "$INSTDIR\bin"
     File "${INPDIR}\bin\drivedb.h"
@@ -171,7 +187,7 @@ SectionGroupEnd
 
 Section "!Documentation" DOC_SECTION
 
-  SectionIn 1 2
+  SectionIn ${FULL_TYPES} ${EXTRACT_TYPES}
 
   SetOutPath "$INSTDIR\doc"
   File "${INPDIR}\doc\AUTHORS.txt"
@@ -183,10 +199,11 @@ Section "!Documentation" DOC_SECTION
   File "${INPDIR}\doc\README.txt"
   File "${INPDIR}\doc\TODO.txt"
 !ifdef INPDIR64
-  StrCmp $X64 "" +3
+  ${If} $X64 != ""
     File "${INPDIR64}\doc\checksums64.txt"
-  GoTo +2
+  ${Else}
     File "${INPDIR}\doc\checksums32.txt"
+  ${EndIf}
 !else
   File "${INPDIR}\doc\checksums??.txt"
 !endif
@@ -202,7 +219,7 @@ SectionEnd
 
 Section "Uninstaller" UNINST_SECTION
 
-  SectionIn 1
+  SectionIn ${FULL_TYPES}
   AddSize 40
 
   CreateDirectory "$INSTDIR"
@@ -210,8 +227,9 @@ Section "Uninstaller" UNINST_SECTION
   ; Keep old Install_Dir registry entry for GSmartControl
   ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\GSmartControl" "InstallLocation"
   ReadRegStr $1 HKLM "Software\smartmontools" "Install_Dir"
-  StrCmp "$0$1" "" +2 0
+  ${If} "$0$1" != ""
     WriteRegStr HKLM "Software\smartmontools" "Install_Dir" "$INSTDIR"
+  ${EndIf}
 
   ; Write uninstall keys and program
   WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\smartmontools" "DisplayName" "smartmontools"
@@ -221,9 +239,9 @@ Section "Uninstaller" UNINST_SECTION
   WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\smartmontools" "InstallLocation" "$INSTDIR"
   WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\smartmontools" "UninstallString" '"$INSTDIR\uninst-smartmontools.exe"'
   WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\smartmontools" "Publisher"     "smartmontools.org"
-  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\smartmontools" "URLInfoAbout"  "http://www.smartmontools.org/"
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\smartmontools" "URLInfoAbout"  "https://www.smartmontools.org/"
   WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\smartmontools" "HelpLink"      "http://sourceforge.net/projects/smartmontools/support"
-  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\smartmontools" "URLUpdateInfo" "http://smartmontools.no-ip.org/"
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\smartmontools" "URLUpdateInfo" "http://builds.smartmontools.org/"
   WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\smartmontools" "NoModify" 1
   WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\smartmontools" "NoRepair" 1
   WriteUninstaller "uninst-smartmontools.exe"
@@ -232,7 +250,7 @@ SectionEnd
 
 Section "Start Menu Shortcuts" MENU_SECTION
 
-  SectionIn 1
+  SectionIn ${FULL_TYPES}
 
   SetShellVarContext all
 
@@ -245,15 +263,15 @@ Section "Start Menu Shortcuts" MENU_SECTION
   !macroend
 
   ; runcmdu
-  IfFileExists "$INSTDIR\bin\smartctl.exe" 0 +2
-  IfFileExists "$INSTDIR\bin\smartd.exe" 0 noruncmd
+  ${If}   ${FileExists} "$INSTDIR\bin\smartctl.exe"
+  ${OrIf} ${FileExists} "$INSTDIR\bin\smartd.exe"
     SetOutPath "$INSTDIR\bin"
     !insertmacro FileExe "bin\runcmdu.exe" ""
-    File "${INPDIR}\bin\runcmdu.exe.manifest"
-  noruncmd:
+    Delete "$INSTDIR\bin\runcmdu.exe.manifest" ; TODO: Remove after smartmontools 6.5
+  ${EndIf}
 
   ; smartctl
-  IfFileExists "$INSTDIR\bin\smartctl.exe" 0 noctl
+  ${If} ${FileExists} "$INSTDIR\bin\smartctl.exe"
     SetOutPath "$INSTDIR\bin"
     !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartctl (Admin CMD).lnk" "$WINDIR\system32\cmd.exe" '/k PATH=$INSTDIR\bin;%PATH%&cd /d "$INSTDIR\bin"'
     CreateDirectory "$SMPROGRAMS\smartmontools\smartctl Examples"
@@ -273,10 +291,10 @@ Section "Start Menu Shortcuts" MENU_SECTION
     !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartctl Examples\Stop(Abort) selftest (-X).lnk"        "$INSTDIR\bin\runcmdu.exe" "smartctl -X sda"
     !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartctl Examples\Turn SMART off (-s off).lnk"          "$INSTDIR\bin\runcmdu.exe" "smartctl -s off sda"
     !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartctl Examples\Turn SMART on (-s on).lnk"            "$INSTDIR\bin\runcmdu.exe" "smartctl -s on sda"
-  noctl:
+  ${EndIf}
 
   ; smartd
-  IfFileExists "$INSTDIR\bin\smartd.exe" 0 nod
+  ${If} ${FileExists} "$INSTDIR\bin\smartd.exe"
     SetOutPath "$INSTDIR\bin"
     CreateDirectory "$SMPROGRAMS\smartmontools\smartd Examples"
     !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartd Examples\Daemon start, smartd.log.lnk"           "$INSTDIR\bin\runcmdu.exe" "smartd -l local0"
@@ -295,10 +313,10 @@ Section "Start Menu Shortcuts" MENU_SECTION
     !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartd Examples\Service remove.lnk"                     "$INSTDIR\bin\runcmdu.exe" "smartd remove"
     !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartd Examples\Service start.lnk"                      "$INSTDIR\bin\runcmdu.exe" "net start smartd"
     !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartd Examples\Service stop.lnk"                       "$INSTDIR\bin\runcmdu.exe" "net stop smartd"
-  nod:
+  ${EndIf}
 
   ; Documentation
-  IfFileExists "$INSTDIR\doc\README.TXT" 0 nodoc
+  ${If} ${FileExists} "$INSTDIR\doc\README.TXT"
     SetOutPath "$INSTDIR\doc"
     CreateDirectory "$SMPROGRAMS\smartmontools\Documentation"
     CreateShortCut "$SMPROGRAMS\smartmontools\Documentation\smartctl manual page (html).lnk"    "$INSTDIR\doc\smartctl.8.html"
@@ -308,36 +326,36 @@ Section "Start Menu Shortcuts" MENU_SECTION
     CreateShortCut "$SMPROGRAMS\smartmontools\Documentation\smartd manual page (txt).lnk"       "$INSTDIR\doc\smartd.8.txt"
     CreateShortCut "$SMPROGRAMS\smartmontools\Documentation\smartd.conf manual page (txt).lnk"  "$INSTDIR\doc\smartd.conf.5.txt"
     CreateShortCut "$SMPROGRAMS\smartmontools\Documentation\smartd.conf sample.lnk" "$EDITOR" "$INSTDIR\doc\smartd.conf"
-    IfFileExists "$INSTDIR\bin\drivedb.h" 0 nodb
+    ${If} ${FileExists} "$INSTDIR\bin\drivedb.h"
         CreateShortCut "$SMPROGRAMS\smartmontools\Documentation\drivedb.h (view).lnk" "$EDITOR" "$INSTDIR\bin\drivedb.h"
         !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\Documentation\drivedb-add.h (create, edit).lnk" "$EDITOR" "$INSTDIR\bin\drivedb-add.h"
-    nodb:
+    ${EndIf}
     CreateShortCut "$SMPROGRAMS\smartmontools\Documentation\ChangeLog.lnk" "$INSTDIR\doc\ChangeLog.txt"
     CreateShortCut "$SMPROGRAMS\smartmontools\Documentation\COPYING.lnk"   "$INSTDIR\doc\COPYING.txt"
     CreateShortCut "$SMPROGRAMS\smartmontools\Documentation\NEWS.lnk"      "$INSTDIR\doc\NEWS.txt"
-    CreateShortCut "$SMPROGRAMS\smartmontools\Documentation\Windows version download page.lnk" "http://smartmontools.no-ip.org/"
-  nodoc:
+  ${EndIf}
 
   ; Homepage
-  CreateShortCut "$SMPROGRAMS\smartmontools\smartmontools Home Page.lnk" "http://www.smartmontools.org/"
+  CreateShortCut "$SMPROGRAMS\smartmontools\smartmontools Home Page.lnk" "https://www.smartmontools.org/"
+  CreateShortCut "$SMPROGRAMS\smartmontools\smartmontools Daily Builds.lnk" "http://builds.smartmontools.org/"
 
   ; drivedb.h update
-  IfFileExists "$INSTDIR\bin\update-smart-drivedb.exe" 0 noupdb
+  ${If} ${FileExists} "$INSTDIR\bin\update-smart-drivedb.exe"
     SetOutPath "$INSTDIR\bin"
     !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\drivedb.h update.lnk" "$INSTDIR\bin\update-smart-drivedb.exe" ""
-  noupdb:
+  ${EndIf}
 
   ; Uninstall
-  IfFileExists "$INSTDIR\uninst-smartmontools.exe" 0 noinst
+  ${If} ${FileExists} "$INSTDIR\uninst-smartmontools.exe"
     SetOutPath "$INSTDIR"
     !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\Uninstall smartmontools.lnk" "$INSTDIR\uninst-smartmontools.exe" ""
-  noinst:
+  ${EndIf}
 
 SectionEnd
 
 Section "Add install dir to PATH" PATH_SECTION
 
-  SectionIn 1
+  SectionIn ${FULL_TYPES}
 
   Push "$INSTDIR\bin"
   Call AddToPath
@@ -357,13 +375,13 @@ SectionGroup "Add smartctl to drive menu"
 !macroend
 
   Section "Remove existing entries first" DRIVE_REMOVE_SECTION
-    SectionIn 3
+    SectionIn ${DRIVEMENU_TYPE}
     !insertmacro DriveMenuRemove
   SectionEnd
 
 !macro DriveSection id name args
   Section 'smartctl ${args} ...' DRIVE_${id}_SECTION
-    SectionIn 3
+    SectionIn ${DRIVEMENU_TYPE}
     Call CheckRunCmdA
     DetailPrint 'Add drive menu entry "${name}": smartctl ${args} ...'
     WriteRegStr HKCR "Drive\shell\smartctl${id}" "" "${name}"
@@ -385,37 +403,40 @@ SectionGroupEnd
 Section "Uninstall"
   
   ; Stop & remove service
-  IfFileExists "$INSTDIR\bin\smartd.exe" 0 nosrv
+  ${If} ${FileExists} "$INSTDIR\bin\smartd.exe"
     ReadRegStr $0 HKLM "System\CurrentControlSet\Services\smartd" "ImagePath"
-    StrCmp $0 "" nosrv
+    ${If} $0 != ""
       ExecWait "net stop smartd"
-      MessageBox MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2  "Remove smartd service ?" /SD IDNO IDYES 0 IDNO nosrv
+      MessageBox MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2  "Remove smartd service ?" /SD IDNO IDYES 0 IDNO +2
         ExecWait "$INSTDIR\bin\smartd.exe remove"
-  nosrv:
+    ${EndIf}
+  ${EndIf}
 
   ; Remove installer registry keys
   DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\smartmontools"
   DeleteRegKey HKLM "Software\smartmontools"
 
   ; Remove conf file ?
-  IfFileExists "$INSTDIR\bin\smartd.conf" 0 noconf
+  ${If} ${FileExists} "$INSTDIR\bin\smartd.conf"
     ; Assume unchanged if timestamp is equal to sample file
     GetFileTime "$INSTDIR\bin\smartd.conf" $0 $1
     GetFileTime "$INSTDIR\doc\smartd.conf" $2 $3
     StrCmp "$0:$1" "$2:$3" +2 0
-      MessageBox MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2  "Delete configuration file$\n$INSTDIR\bin\smartd.conf ?" /SD IDNO IDYES 0 IDNO noconf
+      MessageBox MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2  "Delete configuration file$\n$INSTDIR\bin\smartd.conf ?" /SD IDNO IDYES 0 IDNO +2
         Delete "$INSTDIR\bin\smartd.conf"
-  noconf:
+  ${EndIf}
 
   ; Remove log file ?
-  IfFileExists "$INSTDIR\bin\smartd.log" 0 +3
+  ${If} ${FileExists} "$INSTDIR\bin\smartd.log"
     MessageBox MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2  "Delete log file$\n$INSTDIR\bin\smartd.log ?" /SD IDNO IDYES 0 IDNO +2
       Delete "$INSTDIR\bin\smartd.log"
+  ${EndIf}
 
   ; Remove drivedb-add file ?
-  IfFileExists "$INSTDIR\bin\drivedb-add.h" 0 +3
+  ${If} ${FileExists} "$INSTDIR\bin\drivedb-add.h"
     MessageBox MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2  "Delete local drive database file$\n$INSTDIR\bin\drivedb-add.h ?" /SD IDNO IDYES 0 IDNO +2
       Delete "$INSTDIR\bin\drivedb-add.h"
+  ${EndIf}
 
   ; Remove files
   Delete "$INSTDIR\bin\smartctl.exe"
@@ -431,9 +452,9 @@ Section "Uninstall"
   Delete "$INSTDIR\bin\smartd-run.bat"
   Delete "$INSTDIR\bin\net-run.bat"
   Delete "$INSTDIR\bin\runcmda.exe"
-  Delete "$INSTDIR\bin\runcmda.exe.manifest"
+  Delete "$INSTDIR\bin\runcmda.exe.manifest" ; TODO: Remove after smartmontools 6.5
   Delete "$INSTDIR\bin\runcmdu.exe"
-  Delete "$INSTDIR\bin\runcmdu.exe.manifest"
+  Delete "$INSTDIR\bin\runcmdu.exe.manifest" ; TODO: Remove after smartmontools 6.5
   Delete "$INSTDIR\bin\wtssendmsg.exe"
   Delete "$INSTDIR\doc\AUTHORS.txt"
   Delete "$INSTDIR\doc\ChangeLog.txt"
@@ -477,14 +498,15 @@ Section "Uninstall"
   !insertmacro DriveMenuRemove
 
   ; Check for still existing entries
-  IfFileExists "$INSTDIR\bin\smartd.exe" 0 +3
+  ${If} ${FileExists} "$INSTDIR\bin\smartd.exe"
     MessageBox MB_OK|MB_ICONEXCLAMATION "$INSTDIR\bin\smartd.exe could not be removed.$\nsmartd is possibly still running." /SD IDOK
-    Goto +3
-  IfFileExists "$INSTDIR" 0 +2
+  ${ElseIf} ${FileExists} "$INSTDIR"
     MessageBox MB_OK "Note: $INSTDIR could not be removed." /SD IDOK
+  ${EndIf}
 
-  IfFileExists "$SMPROGRAMS\smartmontools" 0 +2
+  ${If} ${FileExists} "$SMPROGRAMS\smartmontools"
     MessageBox MB_OK "Note: $SMPROGRAMS\smartmontools could not be removed." /SD IDOK
+  ${EndIf}
 
 SectionEnd
 
@@ -500,19 +522,32 @@ SectionEnd
 Function .onInit
 
   ; Set default install directories
-  StrCmp $INSTDIR "" 0 endinst ; /D=PATH option specified ?
-  ReadRegStr $INSTDIR HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\smartmontools" "InstallLocation"
-  StrCmp $INSTDIR "" 0 endinst ; Already installed ?
-  ReadRegStr $INSTDIR HKLM "Software\smartmontools" "Install_Dir"
-  StrCmp $INSTDIR "" 0 endinst ; Already installed ?
-    StrCpy $INSTDIR "$PROGRAMFILES\smartmontools"
+  ${If} $INSTDIR == "" ; /D=PATH option not specified ?
+    ReadRegStr $INSTDIR HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\smartmontools" "InstallLocation"
+    ${If} $INSTDIR == "" ; Not already installed ?
+      ReadRegStr $INSTDIR HKLM "Software\smartmontools" "Install_Dir"
+      ${If} $INSTDIR == "" ; Not already installed (smartmontools < r3911/6.3) ?
+        StrCpy $INSTDIR "$PROGRAMFILES\smartmontools"
 !ifdef INPDIR64
-    StrCpy $INSTDIR32 $INSTDIR
-    StrCpy $INSTDIR64 "$PROGRAMFILES64\smartmontools"
+        StrCpy $INSTDIR32 $INSTDIR
+        StrCpy $INSTDIR64 "$PROGRAMFILES64\smartmontools"
 !endif
-  endinst:
+      ${EndIf}
+    ${EndIf}
+  ${EndIf}
 
 !ifdef INPDIR64
+  ; Check for 64-bit unless already installed in 32-bit location
+  ${If} $INSTDIR64 != ""
+  ${OrIf} $INSTDIR != "$PROGRAMFILES\smartmontools"
+    ; $1 = IsWow64Process(GetCurrentProcess(), ($0=FALSE, &$0))
+    System::Call "kernel32::GetCurrentProcess() i.s"
+    System::Call "kernel32::IsWow64Process(i s, *i 0 r0) i.r1"
+    ${If} "$0 $1" == "1 1" ; 64-bit Windows ?
+      !insertmacro SelectSection ${X64_SECTION}
+    ${EndIf}
+  ${EndIf}
+
   ; Sizes of binary sections include 32-bit and 64-bit executables
   !insertmacro AdjustSectionSize ${SMARTCTL_SECTION}
   !insertmacro AdjustSectionSize ${SMARTD_SECTION}
@@ -521,47 +556,57 @@ Function .onInit
 
   ; Use Notepad++ if installed
   StrCpy $EDITOR "$PROGRAMFILES\Notepad++\notepad++.exe"
-  IfFileExists "$EDITOR" +2 0
+  ${IfNot} ${FileExists} "$EDITOR"
     StrCpy $EDITOR "notepad.exe"
+  ${EndIf}
 
   Call ParseCmdLine
+
+!ifdef INPDIR64
+  Call CheckX64
+!endif
 FunctionEnd
 
 ; Check x64 section and update INSTDIR accordingly
 
 !ifdef INPDIR64
 Function CheckX64
-  SectionGetFlags ${X64_SECTION} $0
-  IntOp $0 $0 & ${SF_SELECTED}
-  IntCmp $0 ${SF_SELECTED} x64
+  ${IfNot} ${SectionIsSelected} ${X64_SECTION}
     StrCpy $X64 ""
-    StrCmp $INSTDIR32 "" +3
+    ${If} $INSTDIR32 != ""
+    ${AndIf} $INSTDIR == $INSTDIR64
       StrCpy $INSTDIR $INSTDIR32
-      StrCpy $INSTDIR32 ""
-    Goto done
-  x64:
+    ${EndIf}
+  ${Else}
     StrCpy $X64 "t"
-    StrCmp $INSTDIR64 "" +3
+    ${If} $INSTDIR64 != ""
+    ${AndIf} $INSTDIR == $INSTDIR32
       StrCpy $INSTDIR $INSTDIR64
-      StrCpy $INSTDIR64 ""
-  done:
+    ${EndIf}
+  ${EndIf}
 FunctionEnd
 !endif
 
 ; Command line parsing
-!macro CheckCmdLineOption name section
-  StrCpy $allopts "$allopts,${name}"
+
+!macro GetCmdLineOption var name
   Push ",$opts,"
   Push ",${name},"
   Call StrStr
-  Pop $0
-  StrCmp $0 "" 0 sel_${name}
-  !insertmacro UnselectSection ${section}
-  Goto done_${name}
-sel_${name}:
-  !insertmacro SelectSection ${section}
-  StrCpy $nomatch ""
-done_${name}:
+  Pop ${var}
+  ${If} ${var} != ""
+    StrCpy $nomatch ""
+  ${EndIf}
+!macroend
+
+!macro CheckCmdLineOption name section
+  StrCpy $allopts "$allopts,${name}"
+  !insertmacro GetCmdLineOption $0 ${name}
+  ${If} $0 == ""
+    !insertmacro UnselectSection ${section}
+  ${Else}
+    !insertmacro SelectSection ${section}
+  ${EndIf}
 !macroend
 
 Function ParseCmdLine
@@ -569,19 +614,30 @@ Function ParseCmdLine
   Var /global opts
   ${GetParameters} $R0
   ${GetOptions} $R0 "/SO" $opts
-  IfErrors 0 +2
+  ${If} ${Errors}
     Return
+  ${EndIf}
   Var /global allopts
-  StrCpy $allopts ""
   Var /global nomatch
   StrCpy $nomatch "t"
-  ; turn sections on or off
 !ifdef INPDIR64
-  !insertmacro CheckCmdLineOption "x64" ${X64_SECTION}
-  Call CheckX64
-  StrCmp $opts "x64" 0 +2
-    Return ; leave sections unchanged if only "x64" is specified
+  ; Change previous 64-bit setting
+  StrCpy $allopts ",x32|x64"
+  !insertmacro GetCmdLineOption $0 "x32"
+  ${If} $0 != ""
+    !insertmacro UnselectSection ${X64_SECTION}
+  ${EndIf}
+  !insertmacro GetCmdLineOption $0 "x64"
+  ${If} $0 != ""
+    !insertmacro SelectSection ${X64_SECTION}
+  ${EndIf}
+  ; Leave other sections unchanged if only "x32" or "x64" is specified
+  ${If}   $opts == "x32"
+  ${OrIf} $opts == "x64"
+    Return
+  ${EndIf}
 !endif
+  ; Turn sections on or off
   !insertmacro CheckCmdLineOption "smartctl" ${SMARTCTL_SECTION}
   !insertmacro CheckCmdLineOption "smartd" ${SMARTD_SECTION}
   !insertmacro CheckCmdLineOption "smartctlnc" ${SMARTCTL_NC_SECTION}
@@ -597,22 +653,25 @@ Function ParseCmdLine
   !insertmacro CheckCmdLineOption "drive3" ${DRIVE_3_SECTION}
   !insertmacro CheckCmdLineOption "drive4" ${DRIVE_4_SECTION}
   !insertmacro CheckCmdLineOption "drive5" ${DRIVE_5_SECTION}
-  StrCmp $opts "-" done
-  StrCmp $nomatch "" done
-    StrCpy $0 "$allopts,-" "" 1
-    MessageBox MB_OK "Usage: smartmontools-VERSION.win32-setup [/S] [/SO component,...] [/D=INSTDIR]$\n$\ncomponents:$\n  $0"
-    Abort
-done:
+  ${If} $opts != "-"
+    ${If} $nomatch != ""
+      StrCpy $0 "$allopts,-" "" 1
+      MessageBox MB_OK "Usage: smartmontools-VERSION.win32-setup [/S] [/SO component,...] [/D=INSTDIR]$\n$\ncomponents:$\n  $0"
+      Abort
+    ${EndIf}
+  ${EndIf}
 FunctionEnd
 
-; Install runcmda.exe if missing
+; Install runcmda.exe only once
 
 Function CheckRunCmdA
-  IfFileExists "$INSTDIR\bin\runcmda.exe" done 0
+  Var /global runcmda
+  ${If} $runcmda == ""
+    StrCpy $runcmda "t"
     SetOutPath "$INSTDIR\bin"
     !insertmacro FileExe "bin\runcmda.exe" ""
-    File "${INPDIR}\bin\runcmda.exe.manifest"
-  done:
+    Delete "$INSTDIR\bin\runcmda.exe.manifest" ; TODO: Remove after smartmontools 6.5
+  ${EndIf}
 FunctionEnd
 
 
@@ -658,16 +717,19 @@ Function AddToPath
   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)"
 
-  IntCmp $4 234 0 +4 +4 ; $4 == ERROR_MORE_DATA
+  ${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}"
+    MessageBox MB_OK "PATH not updated, original length $2 > ${NSIS_MAX_STRLEN}" /SD IDOK
     Goto done
+  ${EndIf}
 
-  IntCmp $4 0 +5 ; $4 != NO_ERROR
-    IntCmp $4 2 +3 ; $4 != ERROR_FILE_NOT_FOUND
+  ${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;"
@@ -686,18 +748,21 @@ Function AddToPath
   StrLen $3 $1
   IntOp $2 $2 + $3
   IntOp $2 $2 + 2 ; $2 = strlen(dir) + strlen(PATH) + sizeof(";")
-  IntCmp $2 ${NSIS_MAX_STRLEN} +4 +4 0
+  ${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}."
+    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
-  StrCmp $2 ";" 0 +2
+  ${If} $2 == ";"
     StrCpy $1 $1 -1 ; remove trailing ';'
-  StrCmp $1 "" +2   ; no leading ';'
+  ${EndIf}
+  ${If} $1 != "" ; no leading ';'
     StrCpy $0 "$1;$0"
+  ${EndIf}
   WriteRegExpandStr ${Environ} "PATH" $0
   SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
 
@@ -727,8 +792,9 @@ Function un.RemoveFromPath
 
   ReadRegStr $1 ${Environ} "PATH"
   StrCpy $5 $1 1 -1
-  StrCmp $5 ";" +2
+  ${If} $5 != ";"
     StrCpy $1 "$1;" ; ensure trailing ';'
+  ${EndIf}
   Push $1
   Push "$0;"
   Call un.StrStr
@@ -742,8 +808,9 @@ Function un.RemoveFromPath
   StrCpy $6 $2 "" $3 ; $6 is now the part after the path to remove
   StrCpy $3 "$5$6"
   StrCpy $5 $3 1 -1
-  StrCmp $5 ";" 0 +2
+  ${If} $5 == ";"
     StrCpy $3 $3 -1 ; remove trailing ';'
+  ${EndIf}
   WriteRegExpandStr ${Environ} "PATH" $3
   SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
 
@@ -778,13 +845,12 @@ Function ${un}StrStr
   StrCpy $R4 0
   ; $R1=substring, $R2=string, $R3=strlen(substring)
   ; $R4=count, $R5=tmp
-  loop:
+  ${Do}
     StrCpy $R5 $R2 $R3 $R4
-    StrCmp $R5 $R1 done
-    StrCmp $R5 "" done
+    ${IfThen} $R5 == $R1 ${|} ${ExitDo} ${|}
+    ${IfThen} $R5 == ""  ${|} ${ExitDo} ${|}
     IntOp $R4 $R4 + 1
-    Goto loop
-done:
+  ${Loop}
   StrCpy $R1 $R2 "" $R4
   Pop $R5
   Pop $R4
@@ -804,8 +870,6 @@ FunctionEnd
 ; http://nsis.sourceforge.net/IShellLink_Set_RunAs_flag
 ;
 
-!include "LogicLib.nsh"
-
 !define IPersistFile {0000010b-0000-0000-c000-000000000046}
 !define CLSID_ShellLink {00021401-0000-0000-C000-000000000046}
 !define IID_IShellLinkA {000214EE-0000-0000-C000-000000000046}
@@ -852,5 +916,5 @@ Function ShellLinkSetRunAs
   ${Else}
     DetailPrint "Set RunAsAdmin: $9"
   ${EndIf}
-  System::Store L ; push $0-$9, $R0-$R9
+  System::Store L ; pop $R9-$R0, $9-$0
 FunctionEnd