nsis.pathupdate.nsh 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. !include "WinMessages.nsh"
  2. ; see https://support.microsoft.com/en-us/kb/104011
  3. !define Environ 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
  4. ; HKEY_LOCAL_MACHINE = 0x80000002
  5. ; AddToPath - Appends dir to PATH
  6. ; (does not work on Win9x/ME)
  7. ;
  8. ; Usage:
  9. ; Push "dir"
  10. ; Call AddToPath
  11. Function AddToPath
  12. Exch $0
  13. Push $1
  14. Push $2
  15. Push $3
  16. Push $4
  17. ; NSIS ReadRegStr returns empty string on string overflow
  18. ; Native calls are used here to check actual length of PATH
  19. ; $4 = RegOpenKey(HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Control\Session Manager\Environment", &$3)
  20. System::Call "advapi32::RegOpenKey(i 0x80000002, t'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', *i.r3) i.r4"
  21. IntCmp $4 0 0 done done
  22. ; $4 = RegQueryValueEx($3, "PATH", (DWORD*)0, (DWORD*)0, &$1, ($2=NSIS_MAX_STRLEN, &$2))
  23. ; RegCloseKey($3)
  24. System::Call "advapi32::RegQueryValueEx(i $3, t'PATH', i 0, i 0, t.r1, *i ${NSIS_MAX_STRLEN} r2) i.r4"
  25. System::Call "advapi32::RegCloseKey(i $3)"
  26. IntCmp $4 234 0 +4 +4 ; $4 == ERROR_MORE_DATA
  27. DetailPrint "AddToPath: original length $2 > ${NSIS_MAX_STRLEN}"
  28. MessageBox MB_OK "PATH not updated, original length $2 > ${NSIS_MAX_STRLEN}"
  29. Goto done
  30. IntCmp $4 0 +5 ; $4 != NO_ERROR
  31. IntCmp $4 2 +3 ; $4 != ERROR_FILE_NOT_FOUND
  32. DetailPrint "AddToPath: unexpected error code $4"
  33. Goto done
  34. StrCpy $1 ""
  35. ; Check if already in PATH
  36. Push "$1;"
  37. Push "$0;"
  38. Call StrStr
  39. Pop $2
  40. StrCmp $2 "" 0 done
  41. Push "$1;"
  42. Push "$0\;"
  43. Call StrStr
  44. Pop $2
  45. StrCmp $2 "" 0 done
  46. ; Prevent NSIS string overflow
  47. StrLen $2 $0
  48. StrLen $3 $1
  49. IntOp $2 $2 + $3
  50. IntOp $2 $2 + 2 ; $2 = strlen(dir) + strlen(PATH) + sizeof(";")
  51. IntCmp $2 ${NSIS_MAX_STRLEN} +4 +4 0
  52. DetailPrint "AddToPath: new length $2 > ${NSIS_MAX_STRLEN}"
  53. MessageBox MB_OK "PATH not updated, new length $2 > ${NSIS_MAX_STRLEN}."
  54. Goto done
  55. ; Append dir to PATH
  56. DetailPrint "Add to PATH: $0"
  57. StrCpy $2 $1 1 -1
  58. StrCmp $2 ";" 0 +2
  59. StrCpy $1 $1 -1 ; remove trailing ';'
  60. StrCmp $1 "" +2 ; no leading ';'
  61. StrCpy $0 "$1;$0"
  62. WriteRegExpandStr ${Environ} "PATH" $0
  63. SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
  64. done:
  65. Pop $4
  66. Pop $3
  67. Pop $2
  68. Pop $1
  69. Pop $0
  70. FunctionEnd
  71. ; RemoveFromPath - Removes dir from PATH
  72. ;
  73. ; Usage:
  74. ; Push "dir"
  75. ; Call RemoveFromPath
  76. Function un.RemoveFromPath
  77. Exch $0
  78. Push $1
  79. Push $2
  80. Push $3
  81. Push $4
  82. Push $5
  83. Push $6
  84. ; NSIS ReadRegStr returns empty string on string overflow
  85. ; Native calls are used here to check actual length of PATH
  86. ; $4 = RegOpenKey(HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Control\Session Manager\Environment", &$3)
  87. System::Call "advapi32::RegOpenKey(i 0x80000002, t'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', *i.r3) i.r4"
  88. IntCmp $4 0 0 done done
  89. ; $4 = RegQueryValueEx($3, "PATH", (DWORD*)0, (DWORD*)0, &$1, ($2=NSIS_MAX_STRLEN, &$2))
  90. ; RegCloseKey($3)
  91. System::Call "advapi32::RegQueryValueEx(i $3, t'PATH', i 0, i 0, t.r1, *i ${NSIS_MAX_STRLEN} r2) i.r4"
  92. System::Call "advapi32::RegCloseKey(i $3)"
  93. IntCmp $4 234 0 +4 +4 ; $4 == ERROR_MORE_DATA
  94. DetailPrint "RemoveFromPath: original length $2 > ${NSIS_MAX_STRLEN}"
  95. MessageBox MB_OK "PATH not updated, original length $2 > ${NSIS_MAX_STRLEN}"
  96. Goto done
  97. IntCmp $4 0 +5 ; $4 != NO_ERROR
  98. IntCmp $4 2 +3 ; $4 != ERROR_FILE_NOT_FOUND
  99. DetailPrint "RemoveFromPath: unexpected error code $4"
  100. Goto done
  101. StrCpy $1 ""
  102. ; length < ${NSIS_MAX_STRLEN} -> ReadRegStr can be used
  103. ReadRegStr $1 ${Environ} "PATH"
  104. StrCpy $5 $1 1 -1
  105. StrCmp $5 ";" +2
  106. StrCpy $1 "$1;" ; ensure trailing ';'
  107. Push $1
  108. Push "$0;"
  109. Call un.StrStr
  110. Pop $2 ; pos of our dir
  111. StrCmp $2 "" done
  112. DetailPrint "Remove from PATH: $0"
  113. StrLen $3 "$0;"
  114. StrLen $4 $2
  115. StrCpy $5 $1 -$4 ; $5 is now the part before the path to remove
  116. StrCpy $6 $2 "" $3 ; $6 is now the part after the path to remove
  117. StrCpy $3 "$5$6"
  118. StrCpy $5 $3 1 -1
  119. StrCmp $5 ";" 0 +2
  120. StrCpy $3 $3 -1 ; remove trailing ';'
  121. WriteRegExpandStr ${Environ} "PATH" $3
  122. SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
  123. done:
  124. Pop $6
  125. Pop $5
  126. Pop $4
  127. Pop $3
  128. Pop $2
  129. Pop $1
  130. Pop $0
  131. FunctionEnd