1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
!include "WinMessages.nsh"
; see https://support.microsoft.com/en-us/kb/104011
!define Environ 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
; HKEY_LOCAL_MACHINE = 0x80000002
; AddToPath - Appends dir to 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_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Control\Session Manager\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)"
IntCmp $4 234 0 +4 +4 ; $4 == ERROR_MORE_DATA
DetailPrint "AddToPath: original length $2 > ${NSIS_MAX_STRLEN}"
MessageBox MB_OK "PATH not updated, original length $2 > ${NSIS_MAX_STRLEN}"
Goto done
IntCmp $4 0 +5 ; $4 != NO_ERROR
IntCmp $4 2 +3 ; $4 != ERROR_FILE_NOT_FOUND
DetailPrint "AddToPath: unexpected error code $4"
Goto done
StrCpy $1 ""
; 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(";")
IntCmp $2 ${NSIS_MAX_STRLEN} +4 +4 0
DetailPrint "AddToPath: new length $2 > ${NSIS_MAX_STRLEN}"
MessageBox MB_OK "PATH not updated, new length $2 > ${NSIS_MAX_STRLEN}."
Goto done
; Append dir to PATH
DetailPrint "Add to PATH: $0"
StrCpy $2 $1 1 -1
StrCmp $2 ";" 0 +2
StrCpy $1 $1 -1 ; remove trailing ';'
StrCmp $1 "" +2 ; no leading ';'
StrCpy $0 "$1;$0"
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 PATH
;
; Usage:
; Push "dir"
; Call RemoveFromPath
Function un.RemoveFromPath
Exch $0
Push $1
Push $2
Push $3
Push $4
Push $5
Push $6
; NSIS ReadRegStr returns empty string on string overflow
; Native calls are used here to check actual length of PATH
; $4 = RegOpenKey(HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Control\Session Manager\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)"
IntCmp $4 234 0 +4 +4 ; $4 == ERROR_MORE_DATA
DetailPrint "RemoveFromPath: original length $2 > ${NSIS_MAX_STRLEN}"
MessageBox MB_OK "PATH not updated, original length $2 > ${NSIS_MAX_STRLEN}"
Goto done
IntCmp $4 0 +5 ; $4 != NO_ERROR
IntCmp $4 2 +3 ; $4 != ERROR_FILE_NOT_FOUND
DetailPrint "RemoveFromPath: unexpected error code $4"
Goto done
StrCpy $1 ""
; length < ${NSIS_MAX_STRLEN} -> ReadRegStr can be used
ReadRegStr $1 ${Environ} "PATH"
StrCpy $5 $1 1 -1
StrCmp $5 ";" +2
StrCpy $1 "$1;" ; ensure trailing ';'
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
StrCmp $5 ";" 0 +2
StrCpy $3 $3 -1 ; remove trailing ';'
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
|