1!ifndef _AddToPath_nsh
2!define _AddToPath_nsh
3
4########################
5# Usage Example
6#
7#Section "Add to path"
8#  Push $INSTDIR
9#  Call AddToPath
10#
11#  Push "LIB"
12#  Push "c:\Mylibrary\lib"
13#  Call AddToEnvVar
14#
15#  ;likewise AddToPath could be
16#  Push "PATH"
17#  Push $INSTDIR
18#  Call AddToEnvVar
19#
20#SectionEnd
21#
22## ...
23#
24#Section "uninstall"
25#  # ...
26#  Push $INSTDIR
27#  Call un.RemoveFromPath
28#  # ...
29#  Push "LIB"
30#  Push "c:\Mylibrary\lib"
31#  Call un.RemoveFromEnvVar
32#
33#  ;Likewise RemoveFromPath could be
34#  Push "PATH"
35#  Push $INSTDIR
36#  Call un.RemoveFromEnvVar
37#SectionEnd
38###########################
39
40!verbose 3
41!include "WinMessages.NSH"
42!verbose 4
43
44!ifndef WriteEnvStr_RegKey
45  !ifdef ALL_USERS
46    !define WriteEnvStr_RegKey \
47       'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
48  !else
49    !define WriteEnvStr_RegKey 'HKCU "Environment"'
50  !endif
51!endif
52
53; AddToPath - Adds the given dir to the search path.
54;        Input - head of the stack
55;        Note - Win9x systems requires reboot
56
57Function AddToPath
58  Exch $0
59  Push $1
60  Push $2
61  Push $3
62
63  # don't add if the path doesn't exist
64  IfFileExists "$0\*.*" "" AddToPath_done
65
66  ReadEnvStr $1 PATH
67  Push "$1;"
68  Push "$0;"
69  Call StrStr
70  Pop $2
71  StrCmp $2 "" "" AddToPath_done
72  Push "$1;"
73  Push "$0\;"
74  Call StrStr
75  Pop $2
76  StrCmp $2 "" "" AddToPath_done
77  GetFullPathName /SHORT $3 $0
78  Push "$1;"
79  Push "$3;"
80  Call StrStr
81  Pop $2
82  StrCmp $2 "" "" AddToPath_done
83  Push "$1;"
84  Push "$3\;"
85  Call StrStr
86  Pop $2
87  StrCmp $2 "" "" AddToPath_done
88
89  Call IsNT
90  Pop $1
91  StrCmp $1 1 AddToPath_NT
92    ; Not on NT
93    StrCpy $1 $WINDIR 2
94    FileOpen $1 "$1\autoexec.bat" a
95    FileSeek $1 -1 END
96    FileReadByte $1 $2
97    IntCmp $2 26 0 +2 +2 # DOS EOF
98      FileSeek $1 -1 END # write over EOF
99    FileWrite $1 "$\r$\nSET PATH=%PATH%;$3$\r$\n"
100    FileClose $1
101    SetRebootFlag true
102    Goto AddToPath_done
103
104  AddToPath_NT:
105    ReadRegStr $1 ${WriteEnvStr_RegKey} "PATH"
106    StrCpy $2 $1 1 -1 # copy last char
107    StrCmp $2 ";" 0 +2 # if last char == ;
108      StrCpy $1 $1 -1 # remove last char
109    StrCmp $1 "" AddToPath_NTdoIt
110      StrCpy $0 "$0;$1"
111    AddToPath_NTdoIt:
112      WriteRegExpandStr ${WriteEnvStr_RegKey} "PATH" $0
113      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
114
115  AddToPath_done:
116    Pop $3
117    Pop $2
118    Pop $1
119    Pop $0
120FunctionEnd
121
122; RemoveFromPath - Remove a given dir from the path
123;     Input: head of the stack
124
125Function un.RemoveFromPath
126  Exch $0
127  Push $1
128  Push $2
129  Push $3
130  Push $4
131  Push $5
132  Push $6
133
134  IntFmt $6 "%c" 26 # DOS EOF
135
136  Call un.IsNT
137  Pop $1
138  StrCmp $1 1 unRemoveFromPath_NT
139    ; Not on NT
140    StrCpy $1 $WINDIR 2
141    FileOpen $1 "$1\autoexec.bat" r
142    GetTempFileName $4
143    FileOpen $2 $4 w
144    GetFullPathName /SHORT $0 $0
145    StrCpy $0 "SET PATH=%PATH%;$0"
146    Goto unRemoveFromPath_dosLoop
147
148    unRemoveFromPath_dosLoop:
149      FileRead $1 $3
150      StrCpy $5 $3 1 -1 # read last char
151      StrCmp $5 $6 0 +2 # if DOS EOF
152        StrCpy $3 $3 -1 # remove DOS EOF so we can compare
153      StrCmp $3 "$0$\r$\n" unRemoveFromPath_dosLoopRemoveLine
154      StrCmp $3 "$0$\n" unRemoveFromPath_dosLoopRemoveLine
155      StrCmp $3 "$0" unRemoveFromPath_dosLoopRemoveLine
156      StrCmp $3 "" unRemoveFromPath_dosLoopEnd
157      FileWrite $2 $3
158      Goto unRemoveFromPath_dosLoop
159      unRemoveFromPath_dosLoopRemoveLine:
160        SetRebootFlag true
161        Goto unRemoveFromPath_dosLoop
162
163    unRemoveFromPath_dosLoopEnd:
164      FileClose $2
165      FileClose $1
166      StrCpy $1 $WINDIR 2
167      Delete "$1\autoexec.bat"
168      CopyFiles /SILENT $4 "$1\autoexec.bat"
169      Delete $4
170      Goto unRemoveFromPath_done
171
172  unRemoveFromPath_NT:
173    ReadRegStr $1 ${WriteEnvStr_RegKey} "PATH"
174    StrCpy $5 $1 1 -1 # copy last char
175    StrCmp $5 ";" +2 # if last char != ;
176      StrCpy $1 "$1;" # append ;
177    Push $1
178    Push "$0;"
179    Call un.StrStr ; Find `$0;` in $1
180    Pop $2 ; pos of our dir
181    StrCmp $2 "" unRemoveFromPath_done
182      ; else, it is in path
183      # $0 - path to add
184      # $1 - path var
185      StrLen $3 "$0;"
186      StrLen $4 $2
187      StrCpy $5 $1 -$4 # $5 is now the part before the path to remove
188      StrCpy $6 $2 "" $3 # $6 is now the part after the path to remove
189      StrCpy $3 $5$6
190
191      StrCpy $5 $3 1 -1 # copy last char
192      StrCmp $5 ";" 0 +2 # if last char == ;
193        StrCpy $3 $3 -1 # remove last char
194
195      WriteRegExpandStr ${WriteEnvStr_RegKey} "PATH" $3
196      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
197
198  unRemoveFromPath_done:
199    Pop $6
200    Pop $5
201    Pop $4
202    Pop $3
203    Pop $2
204    Pop $1
205    Pop $0
206FunctionEnd
207
208
209
210; AddToEnvVar - Adds the given value to the given environment var
211;        Input - head of the stack $0 environement variable $1=value to add
212;        Note - Win9x systems requires reboot
213
214Function AddToEnvVar
215
216  Exch $1 ; $1 has environment variable value
217  Exch
218  Exch $0 ; $0 has environment variable name
219
220  DetailPrint "Adding $1 to $0"
221  Push $2
222  Push $3
223  Push $4
224
225
226  ReadEnvStr $2 $0
227  Push "$2;"
228  Push "$1;"
229  Call StrStr
230  Pop $3
231  StrCmp $3 "" "" AddToEnvVar_done
232
233  Push "$2;"
234  Push "$1\;"
235  Call StrStr
236  Pop $3
237  StrCmp $3 "" "" AddToEnvVar_done
238
239
240  Call IsNT
241  Pop $2
242  StrCmp $2 1 AddToEnvVar_NT
243    ; Not on NT
244    StrCpy $2 $WINDIR 2
245    FileOpen $2 "$2\autoexec.bat" a
246    FileSeek $2 -1 END
247    FileReadByte $2 $3
248    IntCmp $3 26 0 +2 +2 # DOS EOF
249      FileSeek $2 -1 END # write over EOF
250    FileWrite $2 "$\r$\nSET $0=%$0%;$4$\r$\n"
251    FileClose $2
252    SetRebootFlag true
253    Goto AddToEnvVar_done
254
255  AddToEnvVar_NT:
256    ReadRegStr $2 ${WriteEnvStr_RegKey} $0
257    StrCpy $3 $2 1 -1 # copy last char
258    StrCmp $3 ";" 0 +2 # if last char == ;
259      StrCpy $2 $2 -1 # remove last char
260    StrCmp $2 "" AddToEnvVar_NTdoIt
261      StrCpy $1 "$2;$1"
262    AddToEnvVar_NTdoIt:
263      WriteRegExpandStr ${WriteEnvStr_RegKey} $0 $1
264      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
265
266  AddToEnvVar_done:
267    Pop $4
268    Pop $3
269    Pop $2
270	Pop $1
271    Pop $0
272
273FunctionEnd
274
275; RemoveFromEnvVar - Remove a given value from a environment var
276;     Input: head of the stack
277
278Function un.RemoveFromEnvVar
279
280  Exch $1 ; $1 has environment variable value
281  Exch
282  Exch $0 ; $0 has environment variable name
283
284  DetailPrint "Removing $1 from $0"
285  Push $2
286  Push $3
287  Push $4
288  Push $5
289  Push $6
290  Push $7
291
292  IntFmt $7 "%c" 26 # DOS EOF
293
294  Call un.IsNT
295  Pop $2
296  StrCmp $2 1 unRemoveFromEnvVar_NT
297    ; Not on NT
298    StrCpy $2 $WINDIR 2
299    FileOpen $2 "$2\autoexec.bat" r
300    GetTempFileName $5
301    FileOpen $3 $5 w
302    GetFullPathName /SHORT $1 $1
303    StrCpy $1 "SET $0=%$0%;$1"
304    Goto unRemoveFromEnvVar_dosLoop
305
306    unRemoveFromEnvVar_dosLoop:
307      FileRead $2 $4
308      StrCpy $6 $4 1 -1 # read last char
309      StrCmp $6 $7 0 +2 # if DOS EOF
310        StrCpy $4 $4 -1 # remove DOS EOF so we can compare
311      StrCmp $4 "$1$\r$\n" unRemoveFromEnvVar_dosLoopRemoveLine
312      StrCmp $4 "$1$\n" unRemoveFromEnvVar_dosLoopRemoveLine
313      StrCmp $4 "$1" unRemoveFromEnvVar_dosLoopRemoveLine
314      StrCmp $4 "" unRemoveFromEnvVar_dosLoopEnd
315      FileWrite $3 $4
316      Goto unRemoveFromEnvVar_dosLoop
317      unRemoveFromEnvVar_dosLoopRemoveLine:
318        SetRebootFlag true
319        Goto unRemoveFromEnvVar_dosLoop
320
321    unRemoveFromEnvVar_dosLoopEnd:
322      FileClose $3
323      FileClose $2
324      StrCpy $2 $WINDIR 2
325      Delete "$2\autoexec.bat"
326      CopyFiles /SILENT $5 "$2\autoexec.bat"
327      Delete $5
328      Goto unRemoveFromEnvVar_done
329
330  unRemoveFromEnvVar_NT:
331    ReadRegStr $2 ${WriteEnvStr_RegKey} $0
332    StrCpy $6 $2 1 -1 # copy last char
333    StrCmp $6 ";" +2 # if last char != ;
334      StrCpy $2 "$2;" # append ;
335    Push $2
336    Push "$1;"
337    Call un.StrStr ; Find `$1;` in $2
338    Pop $3 ; pos of our dir
339    StrCmp $3 "" unRemoveFromEnvVar_done
340      ; else, it is in path
341      # $1 - path to add
342      # $2 - path var
343      StrLen $4 "$1;"
344      StrLen $5 $3
345      StrCpy $6 $2 -$5 # $6 is now the part before the path to remove
346      StrCpy $7 $3 "" $4 # $7 is now the part after the path to remove
347      StrCpy $4 $6$7
348
349      StrCpy $6 $4 1 -1 # copy last char
350      StrCmp $6 ";" 0 +2 # if last char == ;
351      StrCpy $4 $4 -1 # remove last char
352
353      WriteRegExpandStr ${WriteEnvStr_RegKey} $0 $4
354      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
355
356  unRemoveFromEnvVar_done:
357    Pop $7
358    Pop $6
359    Pop $5
360    Pop $4
361    Pop $3
362    Pop $2
363    Pop $1
364	Pop $0
365FunctionEnd
366
367
368
369
370!ifndef IsNT_KiCHiK
371!define IsNT_KiCHiK
372
373###########################################
374#            Utility Functions            #
375###########################################
376
377; IsNT
378; no input
379; output, top of the stack = 1 if NT or 0 if not
380;
381; Usage:
382;   Call IsNT
383;   Pop $R0
384;  ($R0 at this point is 1 or 0)
385
386!macro IsNT un
387Function ${un}IsNT
388  Push $0
389  ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion
390  StrCmp $0 "" 0 IsNT_yes
391  ; we are not NT.
392  Pop $0
393  Push 0
394  Return
395
396  IsNT_yes:
397    ; NT!!!
398    Pop $0
399    Push 1
400FunctionEnd
401!macroend
402!insertmacro IsNT ""
403!insertmacro IsNT "un."
404
405!endif ; IsNT_KiCHiK
406
407; StrStr
408; input, top of stack = string to search for
409;        top of stack-1 = string to search in
410; output, top of stack (replaces with the portion of the string remaining)
411; modifies no other variables.
412;
413; Usage:
414;   Push "this is a long ass string"
415;   Push "ass"
416;   Call StrStr
417;   Pop $R0
418;  ($R0 at this point is "ass string")
419
420!macro StrStr un
421Function ${un}StrStr
422Exch $R1 ; st=haystack,old$R1, $R1=needle
423  Exch    ; st=old$R1,haystack
424  Exch $R2 ; st=old$R1,old$R2, $R2=haystack
425  Push $R3
426  Push $R4
427  Push $R5
428  StrLen $R3 $R1
429  StrCpy $R4 0
430  ; $R1=needle
431  ; $R2=haystack
432  ; $R3=len(needle)
433  ; $R4=cnt
434  ; $R5=tmp
435  loop:
436    StrCpy $R5 $R2 $R3 $R4
437    StrCmp $R5 $R1 done
438    StrCmp $R5 "" done
439    IntOp $R4 $R4 + 1
440    Goto loop
441done:
442  StrCpy $R1 $R2 "" $R4
443  Pop $R5
444  Pop $R4
445  Pop $R3
446  Pop $R2
447  Exch $R1
448FunctionEnd
449!macroend
450!insertmacro StrStr ""
451!insertmacro StrStr "un."
452
453!endif ; _AddToPath_nsh
454