path.nsh 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. Var InstallerPath
  2. Var InstallerError
  3. ; Reject reparse points along the selected path before any write or cleanup.
  4. !macro InstallerValidatePathFunction PREFIX
  5. Function ${PREFIX}InstallerValidatePath
  6. StrCpy $InstallerError "$(INSTALLER_PATH_INVALID)"
  7. StrLen $0 $InstallerPath
  8. ${If} $0 < 4
  9. ${OrIf} $0 > 180
  10. Return
  11. ${EndIf}
  12. StrCpy $0 $InstallerPath 2 1
  13. ${If} $0 != ":\"
  14. Return
  15. ${EndIf}
  16. StrCpy $0 $InstallerPath 3
  17. System::Call 'kernel32::GetDriveTypeW(w r0) i.r1'
  18. ${If} $1 != 3
  19. Return
  20. ${EndIf}
  21. StrCpy $1 3
  22. ${Do}
  23. StrCpy $0 $InstallerPath 1 $1
  24. ${If} $0 == ""
  25. ${ExitDo}
  26. ${EndIf}
  27. ${If} $0 == ':'
  28. ${OrIf} $0 == '*'
  29. ${OrIf} $0 == '?'
  30. ${OrIf} $0 == '"'
  31. ${OrIf} $0 == '<'
  32. ${OrIf} $0 == '>'
  33. ${OrIf} $0 == '|'
  34. ${OrIf} $0 == '/'
  35. ${OrIf} $0 == '$\r'
  36. ${OrIf} $0 == '$\n'
  37. ${OrIf} $0 == '$\t'
  38. Return
  39. ${EndIf}
  40. IntOp $1 $1 + 1
  41. ${Loop}
  42. StrCpy $2 $InstallerPath
  43. ${Do}
  44. StrLen $0 $2
  45. ${If} $0 <= 3
  46. ${ExitDo}
  47. ${EndIf}
  48. ${GetFileName} $2 $3
  49. StrCpy $0 $3 1 -1
  50. ${If} $3 == ""
  51. ${OrIf} $0 == "."
  52. ${OrIf} $0 == " "
  53. Return
  54. ${EndIf}
  55. ; Windows reserves device names even when they have an extension.
  56. StrCpy $5 ""
  57. StrCpy $6 0
  58. ${Do}
  59. StrCpy $0 $3 1 $6
  60. ${If} $0 == ""
  61. ${OrIf} $0 == "."
  62. ${ExitDo}
  63. ${EndIf}
  64. StrCpy $5 "$5$0"
  65. IntOp $6 $6 + 1
  66. ${Loop}
  67. ${If} $5 == "CON"
  68. ${OrIf} $5 == "PRN"
  69. ${OrIf} $5 == "AUX"
  70. ${OrIf} $5 == "NUL"
  71. Return
  72. ${EndIf}
  73. StrCpy $0 $5 3
  74. ${If} $0 == "COM"
  75. ${OrIf} $0 == "LPT"
  76. StrLen $0 $5
  77. StrCpy $5 $5 1 3
  78. ${If} $0 == 4
  79. ${AndIf} $5 >= 1
  80. ${AndIf} $5 <= 9
  81. Return
  82. ${EndIf}
  83. ${EndIf}
  84. System::Call 'kernel32::GetFileAttributesW(w r2) i.r0'
  85. ${If} $0 != -1
  86. IntOp $1 $0 & 0x400
  87. IntOp $0 $0 & 0x10
  88. ${If} $1 != 0
  89. ${OrIf} $0 == 0
  90. Return
  91. ${EndIf}
  92. ${EndIf}
  93. ${If} $2 == $WINDIR
  94. ${OrIf} $2 == $PROGRAMFILES32
  95. ${OrIf} $2 == $PROGRAMFILES64
  96. ${OrIf} $2 == $PROFILE
  97. ${OrIf} $2 == $LOCALAPPDATA
  98. ; Ancestors PROFILE and LOCALAPPDATA are allowed; the selected directory itself is not.
  99. ${If} $2 == $WINDIR
  100. ${OrIf} $2 == $PROGRAMFILES32
  101. ${OrIf} $2 == $PROGRAMFILES64
  102. ${OrIf} $2 == $InstallerPath
  103. Return
  104. ${EndIf}
  105. ${EndIf}
  106. ${GetParent} $2 $2
  107. ${Loop}
  108. System::Call 'kernel32::GetFullPathNameW(w "$InstallerPath", i ${NSIS_MAX_STRLEN}, w .r4, p 0) i.r0'
  109. ${If} $0 == 0
  110. ${OrIf} $0 >= ${NSIS_MAX_STRLEN}
  111. Return
  112. ${EndIf}
  113. StrCpy $InstallerPath $4
  114. StrCpy $InstallerError ""
  115. FunctionEnd
  116. !macroend
  117. !insertmacro InstallerValidatePathFunction ""
  118. ; A new installation requires an empty directory; updates require the registered executable.
  119. Function InstallerPreflight
  120. Call InstallerValidatePath
  121. ${If} $InstallerError != ""
  122. Return
  123. ${EndIf}
  124. StrCpy $INSTDIR $InstallerPath
  125. ReadRegStr $0 HKCU "${INSTALL_REGISTRY_KEY}" "InstallLocation"
  126. ${If} $0 != $INSTDIR
  127. ${OrIfNot} ${FileExists} "$INSTDIR\${APP_EXECUTABLE_FILENAME}"
  128. FindFirst $0 $1 "$INSTDIR\*.*"
  129. ${DoWhile} $1 != ""
  130. ${If} $1 != "."
  131. ${AndIf} $1 != ".."
  132. FindClose $0
  133. StrCpy $InstallerError "$(INSTALLER_PATH_OWNERSHIP)"
  134. Return
  135. ${EndIf}
  136. FindNext $0 $1
  137. ${Loop}
  138. FindClose $0
  139. ${EndIf}
  140. StrCpy $2 $INSTDIR
  141. ${Do}
  142. System::Call 'kernel32::GetFileAttributesW(w r2) i.r0'
  143. ${If} $0 != -1
  144. ${ExitDo}
  145. ${EndIf}
  146. ${GetParent} $2 $2
  147. ${Loop}
  148. System::Call 'kernel32::GetTempFileNameW(w r2, w "HIL", i 0, w .r3) i.r0'
  149. ${If} $0 == 0
  150. StrCpy $InstallerError "$(INSTALLER_PATH_WRITABLE)"
  151. Return
  152. ${EndIf}
  153. System::Call 'kernel32::DeleteFileW(w r3)'
  154. System::Call 'kernel32::GetDiskFreeSpaceExW(w r2, *l .r0, p 0, p 0) i.r1'
  155. ${If} $1 == 0
  156. StrCpy $InstallerError "$(INSTALLER_PATH_WRITABLE)"
  157. Return
  158. ${EndIf}
  159. IntOp $2 ${APP_64_UNPACKED_SIZE} + 65536
  160. System::Int64Op $2 * 1024
  161. Pop $2
  162. System::Int64Op $0 < $2
  163. Pop $0
  164. ${If} $0 != 0
  165. StrCpy $InstallerError "$(INSTALLER_DISK_SPACE)"
  166. ${EndIf}
  167. FunctionEnd