1# This Source Code Form is subject to the terms of the Mozilla Public
2# License, v. 2.0. If a copy of the MPL was not distributed with this
3# file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5
6################################################################################
7# Helper defines and macros for toolkit applications
8
9/**
10 * Avoid creating macros / functions that overwrite registers (see the
11 * GetLongPath macro for one way to avoid this)!
12 *
13 * Before using the registers exchange the passed in params and save existing
14 * register values to the stack.
15 *
16 * Exch $R9 ; exhange the original $R9 with the top of the stack
17 * Exch 1   ; exchange the top of the stack with 1 below the top of the stack
18 * Exch $R8 ; exchange the original $R8 with the top of the stack
19 * Exch 2   ; exchange the top of the stack with 2 below the top of the stack
20 * Exch $R7 ; exchange the original $R7 with the top of the stack
21 * Push $R6 ; push the original $R6 onto the top of the stack
22 * Push $R5 ; push the original $R5 onto the top of the stack
23 * Push $R4 ; push the original $R4 onto the top of the stack
24 *
25 * <do stuff>
26 *
27 * ; Restore the values.
28 * Pop $R4  ; restore the value for $R4 from the top of the stack
29 * Pop $R5  ; restore the value for $R5 from the top of the stack
30 * Pop $R6  ; restore the value for $R6 from the top of the stack
31 * Exch $R7 ; exchange the new $R7 value with the top of the stack
32 * Exch 2   ; exchange the top of the stack with 2 below the top of the stack
33 * Exch $R8 ; exchange the new $R8 value with the top of the stack
34 * Exch 1   ; exchange the top of the stack with 2 below the top of the stack
35 * Exch $R9 ; exchange the new $R9 value with the top of the stack
36 *
37 *
38 * When inserting macros in common.nsh from another macro in common.nsh that
39 * can be used from the uninstaller _MOZFUNC_UN will be undefined when it is
40 * inserted. Use the following to redefine _MOZFUNC_UN with its original value
41 * (see the RegCleanMain macro for an example).
42 *
43 * !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN}
44 * !insertmacro ${_MOZFUNC_UN_TMP}FileJoin
45 * !insertmacro ${_MOZFUNC_UN_TMP}LineFind
46 * !insertmacro ${_MOZFUNC_UN_TMP}TextCompareNoDetails
47 * !insertmacro ${_MOZFUNC_UN_TMP}TrimNewLines
48 * !undef _MOZFUNC_UN
49 * !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP}
50 * !undef _MOZFUNC_UN_TMP
51 */
52
53; When including a file provided by NSIS check if its verbose macro is defined
54; to prevent loading the file a second time.
55!ifmacrondef TEXTFUNC_VERBOSE
56  !include TextFunc.nsh
57!endif
58
59!ifmacrondef FILEFUNC_VERBOSE
60  !include FileFunc.nsh
61!endif
62
63!ifmacrondef LOGICLIB_VERBOSITY
64  !include LogicLib.nsh
65!endif
66
67!ifndef WINMESSAGES_INCLUDED
68  !include WinMessages.nsh
69!endif
70
71; When including WinVer.nsh check if ___WINVER__NSH___ is defined to prevent
72; loading the file a second time.
73!ifndef ___WINVER__NSH___
74  !include WinVer.nsh
75!endif
76
77!include x64.nsh
78
79; NSIS provided macros that we have overridden.
80!include overrides.nsh
81
82!define SHORTCUTS_LOG "shortcuts_log.ini"
83!define TO_BE_DELETED "tobedeleted"
84
85; !define SHCNF_DWORD     0x0003
86; !define SHCNF_FLUSH     0x1000
87!ifndef SHCNF_DWORDFLUSH
88  !define SHCNF_DWORDFLUSH 0x1003
89!endif
90!ifndef SHCNE_ASSOCCHANGED
91  !define SHCNE_ASSOCCHANGED 0x08000000
92!endif
93
94################################################################################
95# Macros for debugging
96
97/**
98 * The following two macros assist with verifying that a macro doesn't
99 * overwrite any registers.
100 *
101 * Usage:
102 * ${debugSetRegisters}
103 * <do stuff>
104 * ${debugDisplayRegisters}
105 */
106
107/**
108 * Sets all register values to their name to assist with verifying that a macro
109 * doesn't overwrite any registers.
110 */
111!macro debugSetRegisters
112  StrCpy $0 "$$0"
113  StrCpy $1 "$$1"
114  StrCpy $2 "$$2"
115  StrCpy $3 "$$3"
116  StrCpy $4 "$$4"
117  StrCpy $5 "$$5"
118  StrCpy $6 "$$6"
119  StrCpy $7 "$$7"
120  StrCpy $8 "$$8"
121  StrCpy $9 "$$9"
122  StrCpy $R0 "$$R0"
123  StrCpy $R1 "$$R1"
124  StrCpy $R2 "$$R2"
125  StrCpy $R3 "$$R3"
126  StrCpy $R4 "$$R4"
127  StrCpy $R5 "$$R5"
128  StrCpy $R6 "$$R6"
129  StrCpy $R7 "$$R7"
130  StrCpy $R8 "$$R8"
131  StrCpy $R9 "$$R9"
132!macroend
133!define debugSetRegisters "!insertmacro debugSetRegisters"
134
135/**
136 * Displays all register values to assist with verifying that a macro doesn't
137 * overwrite any registers.
138 */
139!macro debugDisplayRegisters
140  MessageBox MB_OK \
141      "Register Values:$\n\
142       $$0 = $0$\n$$1 = $1$\n$$2 = $2$\n$$3 = $3$\n$$4 = $4$\n\
143       $$5 = $5$\n$$6 = $6$\n$$7 = $7$\n$$8 = $8$\n$$9 = $9$\n\
144       $$R0 = $R0$\n$$R1 = $R1$\n$$R2 = $R2$\n$$R3 = $R3$\n$$R4 = $R4$\n\
145       $$R5 = $R5$\n$$R6 = $R6$\n$$R7 = $R7$\n$$R8 = $R8$\n$$R9 = $R9"
146!macroend
147!define debugDisplayRegisters "!insertmacro debugDisplayRegisters"
148
149
150################################################################################
151# Modern User Interface (MUI) override macros
152
153; Removed macros in nsis 2.33u (ported from nsis 2.22)
154;  MUI_LANGUAGEFILE_DEFINE
155;  MUI_LANGUAGEFILE_LANGSTRING_PAGE
156;  MUI_LANGUAGEFILE_MULTILANGSTRING_PAGE
157;  MUI_LANGUAGEFILE_LANGSTRING_DEFINE
158;  MUI_LANGUAGEFILE_UNLANGSTRING_PAGE
159
160!macro MOZ_MUI_LANGUAGEFILE_DEFINE DEFINE NAME
161
162  !ifndef "${DEFINE}"
163    !define "${DEFINE}" "${${NAME}}"
164  !endif
165  !undef "${NAME}"
166
167!macroend
168
169!macro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE PAGE NAME
170
171  !ifdef MUI_${PAGE}PAGE
172    LangString "${NAME}" 0 "${${NAME}}"
173    !undef "${NAME}"
174  !else
175    !undef "${NAME}"
176  !endif
177
178!macroend
179
180!macro MOZ_MUI_LANGUAGEFILE_MULTILANGSTRING_PAGE PAGE NAME
181
182  !ifdef MUI_${PAGE}PAGE | MUI_UN${PAGE}PAGE
183    LangString "${NAME}" 0 "${${NAME}}"
184    !undef "${NAME}"
185  !else
186    !undef "${NAME}"
187  !endif
188
189!macroend
190
191!macro MOZ_MUI_LANGUAGEFILE_LANGSTRING_DEFINE DEFINE NAME
192
193  !ifdef "${DEFINE}"
194    LangString "${NAME}" 0 "${${NAME}}"
195  !endif
196  !undef "${NAME}"
197
198!macroend
199
200!macro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE PAGE NAME
201
202  !ifdef MUI_UNINSTALLER
203    !ifdef MUI_UN${PAGE}PAGE
204      LangString "${NAME}" 0 "${${NAME}}"
205      !undef "${NAME}"
206    !else
207      !undef "${NAME}"
208    !endif
209  !else
210    !undef "${NAME}"
211  !endif
212
213!macroend
214
215; Modified version of the following MUI macros to support Mozilla localization.
216; MUI_LANGUAGE
217; MUI_LANGUAGEFILE_BEGIN
218; MOZ_MUI_LANGUAGEFILE_END
219; See <NSIS App Dir>/Contrib/Modern UI/System.nsh for more information
220!define MUI_INSTALLOPTIONS_READ "!insertmacro MUI_INSTALLOPTIONS_READ"
221
222!macro MOZ_MUI_LANGUAGE LANGUAGE
223  !verbose push
224  !verbose ${MUI_VERBOSE}
225  !include "${LANGUAGE}.nsh"
226  !verbose pop
227!macroend
228
229!macro MOZ_MUI_LANGUAGEFILE_BEGIN LANGUAGE
230  !insertmacro MUI_INSERT
231  !ifndef "MUI_LANGUAGEFILE_${LANGUAGE}_USED"
232    !define "MUI_LANGUAGEFILE_${LANGUAGE}_USED"
233    LoadLanguageFile "${LANGUAGE}.nlf"
234  !else
235    !error "Modern UI language file ${LANGUAGE} included twice!"
236  !endif
237!macroend
238
239; Custom version of MUI_LANGUAGEFILE_END. The macro to add the default MUI
240; strings and the macros for several strings that are part of the NSIS MUI and
241; not in our locale files have been commented out.
242!macro MOZ_MUI_LANGUAGEFILE_END
243
244#  !include "${NSISDIR}\Contrib\Modern UI\Language files\Default.nsh"
245  !ifdef MUI_LANGUAGEFILE_DEFAULT_USED
246    !undef MUI_LANGUAGEFILE_DEFAULT_USED
247    !warning "${LANGUAGE} Modern UI language file version doesn't match. Using default English texts for missing strings."
248  !endif
249
250  !insertmacro MOZ_MUI_LANGUAGEFILE_DEFINE "MUI_${LANGUAGE}_LANGNAME" "MUI_LANGNAME"
251
252  !ifndef MUI_LANGDLL_PUSHLIST
253    !define MUI_LANGDLL_PUSHLIST "'${MUI_${LANGUAGE}_LANGNAME}' ${LANG_${LANGUAGE}} "
254  !else
255    !ifdef MUI_LANGDLL_PUSHLIST_TEMP
256      !undef MUI_LANGDLL_PUSHLIST_TEMP
257    !endif
258    !define MUI_LANGDLL_PUSHLIST_TEMP "${MUI_LANGDLL_PUSHLIST}"
259    !undef MUI_LANGDLL_PUSHLIST
260    !define MUI_LANGDLL_PUSHLIST "'${MUI_${LANGUAGE}_LANGNAME}' ${LANG_${LANGUAGE}} ${MUI_LANGDLL_PUSHLIST_TEMP}"
261  !endif
262
263  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE WELCOME "MUI_TEXT_WELCOME_INFO_TITLE"
264  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE WELCOME "MUI_TEXT_WELCOME_INFO_TEXT"
265
266!ifdef MUI_TEXT_LICENSE_TITLE
267  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE LICENSE "MUI_TEXT_LICENSE_TITLE"
268!endif
269!ifdef MUI_TEXT_LICENSE_SUBTITLE
270  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE LICENSE "MUI_TEXT_LICENSE_SUBTITLE"
271!endif
272!ifdef MUI_INNERTEXT_LICENSE_TOP
273  !insertmacro MOZ_MUI_LANGUAGEFILE_MULTILANGSTRING_PAGE LICENSE "MUI_INNERTEXT_LICENSE_TOP"
274!endif
275
276#  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE LICENSE "MUI_INNERTEXT_LICENSE_BOTTOM"
277
278!ifdef MUI_INNERTEXT_LICENSE_BOTTOM_CHECKBOX
279  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE LICENSE "MUI_INNERTEXT_LICENSE_BOTTOM_CHECKBOX"
280!endif
281
282!ifdef MUI_INNERTEXT_LICENSE_BOTTOM_RADIOBUTTONS
283  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE LICENSE "MUI_INNERTEXT_LICENSE_BOTTOM_RADIOBUTTONS"
284!endif
285
286  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE COMPONENTS "MUI_TEXT_COMPONENTS_TITLE"
287  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE COMPONENTS "MUI_TEXT_COMPONENTS_SUBTITLE"
288  !insertmacro MOZ_MUI_LANGUAGEFILE_MULTILANGSTRING_PAGE COMPONENTS "MUI_INNERTEXT_COMPONENTS_DESCRIPTION_TITLE"
289  !insertmacro MOZ_MUI_LANGUAGEFILE_MULTILANGSTRING_PAGE COMPONENTS "MUI_INNERTEXT_COMPONENTS_DESCRIPTION_INFO"
290
291  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE DIRECTORY "MUI_TEXT_DIRECTORY_TITLE"
292  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE DIRECTORY "MUI_TEXT_DIRECTORY_SUBTITLE"
293
294  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE STARTMENU "MUI_TEXT_STARTMENU_TITLE"
295  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE STARTMENU "MUI_TEXT_STARTMENU_SUBTITLE"
296  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE STARTMENU "MUI_INNERTEXT_STARTMENU_TOP"
297#  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE STARTMENU "MUI_INNERTEXT_STARTMENU_CHECKBOX"
298
299  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE INSTFILES "MUI_TEXT_INSTALLING_TITLE"
300  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE INSTFILES "MUI_TEXT_INSTALLING_SUBTITLE"
301
302  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE INSTFILES "MUI_TEXT_FINISH_TITLE"
303  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE INSTFILES "MUI_TEXT_FINISH_SUBTITLE"
304
305  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE INSTFILES "MUI_TEXT_ABORT_TITLE"
306  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE INSTFILES "MUI_TEXT_ABORT_SUBTITLE"
307
308  !insertmacro MOZ_MUI_LANGUAGEFILE_MULTILANGSTRING_PAGE FINISH "MUI_BUTTONTEXT_FINISH"
309  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE FINISH "MUI_TEXT_FINISH_INFO_TITLE"
310  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE FINISH "MUI_TEXT_FINISH_INFO_TEXT"
311  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_PAGE FINISH "MUI_TEXT_FINISH_INFO_REBOOT"
312  !insertmacro MOZ_MUI_LANGUAGEFILE_MULTILANGSTRING_PAGE FINISH "MUI_TEXT_FINISH_REBOOTNOW"
313  !insertmacro MOZ_MUI_LANGUAGEFILE_MULTILANGSTRING_PAGE FINISH "MUI_TEXT_FINISH_REBOOTLATER"
314#  !insertmacro MOZ_MUI_LANGUAGEFILE_MULTILANGSTRING_PAGE FINISH "MUI_TEXT_FINISH_RUN"
315#  !insertmacro MOZ_MUI_LANGUAGEFILE_MULTILANGSTRING_PAGE FINISH "MUI_TEXT_FINISH_SHOWREADME"
316
317; Support for using the existing MUI_TEXT_ABORTWARNING string
318!ifdef MOZ_MUI_CUSTOM_ABORT
319    LangString MOZ_MUI_TEXT_ABORTWARNING 0 "${MUI_TEXT_ABORTWARNING}"
320!endif
321
322  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_DEFINE MUI_ABORTWARNING "MUI_TEXT_ABORTWARNING"
323
324
325  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE WELCOME "MUI_UNTEXT_WELCOME_INFO_TITLE"
326  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE WELCOME "MUI_UNTEXT_WELCOME_INFO_TEXT"
327
328  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE CONFIRM "MUI_UNTEXT_CONFIRM_TITLE"
329  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE CONFIRM "MUI_UNTEXT_CONFIRM_SUBTITLE"
330
331#  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE LICENSE "MUI_UNTEXT_LICENSE_TITLE"
332#  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE LICENSE "MUI_UNTEXT_LICENSE_SUBTITLE"
333
334#  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE LICENSE "MUI_UNINNERTEXT_LICENSE_BOTTOM"
335#  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE LICENSE "MUI_UNINNERTEXT_LICENSE_BOTTOM_CHECKBOX"
336#  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE LICENSE "MUI_UNINNERTEXT_LICENSE_BOTTOM_RADIOBUTTONS"
337
338#  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE COMPONENTS "MUI_UNTEXT_COMPONENTS_TITLE"
339#  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE COMPONENTS "MUI_UNTEXT_COMPONENTS_SUBTITLE"
340
341#  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE DIRECTORY "MUI_UNTEXT_DIRECTORY_TITLE"
342#  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE DIRECTORY  "MUI_UNTEXT_DIRECTORY_SUBTITLE"
343
344  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE INSTFILES "MUI_UNTEXT_UNINSTALLING_TITLE"
345  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE INSTFILES "MUI_UNTEXT_UNINSTALLING_SUBTITLE"
346
347  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE INSTFILES "MUI_UNTEXT_FINISH_TITLE"
348  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE INSTFILES "MUI_UNTEXT_FINISH_SUBTITLE"
349
350  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE INSTFILES "MUI_UNTEXT_ABORT_TITLE"
351  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE INSTFILES "MUI_UNTEXT_ABORT_SUBTITLE"
352
353  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE FINISH "MUI_UNTEXT_FINISH_INFO_TITLE"
354  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE FINISH "MUI_UNTEXT_FINISH_INFO_TEXT"
355  !insertmacro MOZ_MUI_LANGUAGEFILE_UNLANGSTRING_PAGE FINISH "MUI_UNTEXT_FINISH_INFO_REBOOT"
356
357  !insertmacro MOZ_MUI_LANGUAGEFILE_LANGSTRING_DEFINE MUI_UNABORTWARNING "MUI_UNTEXT_ABORTWARNING"
358
359  !ifndef MUI_LANGDLL_LANGUAGES
360    !define MUI_LANGDLL_LANGUAGES "'${LANGFILE_${LANGUAGE}_NAME}' '${LANG_${LANGUAGE}}' "
361    !define MUI_LANGDLL_LANGUAGES_CP "'${LANGFILE_${LANGUAGE}_NAME}' '${LANG_${LANGUAGE}}' '${LANG_${LANGUAGE}_CP}' "
362  !else
363    !ifdef MUI_LANGDLL_LANGUAGES_TEMP
364      !undef MUI_LANGDLL_LANGUAGES_TEMP
365    !endif
366    !define MUI_LANGDLL_LANGUAGES_TEMP "${MUI_LANGDLL_LANGUAGES}"
367    !undef MUI_LANGDLL_LANGUAGES
368
369    !ifdef MUI_LANGDLL_LANGUAGES_CP_TEMP
370      !undef MUI_LANGDLL_LANGUAGES_CP_TEMP
371    !endif
372    !define MUI_LANGDLL_LANGUAGES_CP_TEMP "${MUI_LANGDLL_LANGUAGES_CP}"
373    !undef MUI_LANGDLL_LANGUAGES_CP
374
375    !define MUI_LANGDLL_LANGUAGES "'${LANGFILE_${LANGUAGE}_NAME}' '${LANG_${LANGUAGE}}' ${MUI_LANGDLL_LANGUAGES_TEMP}"
376    !define MUI_LANGDLL_LANGUAGES_CP "'${LANGFILE_${LANGUAGE}_NAME}' '${LANG_${LANGUAGE}}' '${LANG_${LANGUAGE}_CP}' ${MUI_LANGDLL_LANGUAGES_CP_TEMP}"
377  !endif
378
379!macroend
380
381/**
382 * Creates an InstallOptions file with a UTF-16LE BOM and adds the RTL value
383 * to the Settings section.
384 *
385 * @param   _FILE
386 *          The name of the file to be created in $PLUGINSDIR.
387 */
388!macro InitInstallOptionsFile _FILE
389  Push $R9
390
391  FileOpen $R9 "$PLUGINSDIR\${_FILE}" w
392  FileWriteWord $R9 "65279"
393  FileClose $R9
394  WriteIniStr "$PLUGINSDIR\${_FILE}" "Settings" "RTL" "$(^RTL)"
395
396  Pop $R9
397!macroend
398
399
400################################################################################
401# Macros for handling files in use
402
403/**
404 * Checks for files in use in the $INSTDIR directory. To check files in
405 * sub-directories this macro would need to be rewritten to create
406 * sub-directories in the temporary directory used to backup the files that are
407 * checked.
408 *
409 * Example usage:
410 *
411 *  ; The first string to be pushed onto the stack MUST be "end" to indicate
412 *  ; that there are no more files in the $INSTDIR directory to check.
413 *  Push "end"
414 *  Push "freebl3.dll"
415 *  ; The last file pushed should be the app's main exe so if it is in use this
416 *  ; macro will return after the first check.
417 *  Push "${FileMainEXE}"
418 *  ${CheckForFilesInUse} $R9
419 *
420 * !IMPORTANT - this macro uses the $R7, $R8, and $R9 registers and makes no
421 *              attempt to restore their original values.
422 *
423 * @return  _RESULT
424 *          false if all of the files popped from the stack are not in use.
425 *          True if any of the files popped from the stack are in use.
426 * $R7 = Temporary backup directory where the files will be copied to.
427 * $R8 = value popped from the stack. This will either be a file name for a file
428 *       in the $INSTDIR directory or "end" to indicate that there are no
429 *       additional files to check.
430 * $R9 = _RESULT
431 */
432!macro CheckForFilesInUse
433
434  !ifndef ${_MOZFUNC_UN}CheckForFilesInUse
435    !verbose push
436    !verbose ${_MOZFUNC_VERBOSE}
437    !define ${_MOZFUNC_UN}CheckForFilesInUse "!insertmacro ${_MOZFUNC_UN}CheckForFilesInUseCall"
438
439    Function ${_MOZFUNC_UN}CheckForFilesInUse
440      ; Create a temporary backup directory.
441      GetTempFileName $R7 "$INSTDIR"
442      Delete "$R7"
443      SetOutPath "$R7"
444      StrCpy $R9 "false"
445
446      Pop $R8
447      ${While} $R8 != "end"
448        ${Unless} ${FileExists} "$INSTDIR\$R8"
449          Pop $R8 ; get next file to check before continuing
450          ${Continue}
451        ${EndUnless}
452
453        ClearErrors
454        CopyFiles /SILENT "$INSTDIR\$R8" "$R7\$R8" ; try to copy
455        ${If} ${Errors}
456          ; File is in use
457          StrCpy $R9 "true"
458          ${Break}
459        ${EndIf}
460
461        Delete "$INSTDIR\$R8" ; delete original
462        ${If} ${Errors}
463          ; File is in use
464          StrCpy $R9 "true"
465          Delete "$R7\$R8" ; delete temp copy
466          ${Break}
467        ${EndIf}
468
469        Pop $R8 ; get next file to check
470      ${EndWhile}
471
472      ; clear stack
473      ${While} $R8 != "end"
474        Pop $R8
475      ${EndWhile}
476
477      ; restore everything
478      SetOutPath "$INSTDIR"
479      CopyFiles /SILENT "$R7\*" "$INSTDIR\"
480      RmDir /r "$R7"
481      SetOutPath "$EXEDIR"
482      ClearErrors
483
484      Push $R9
485    FunctionEnd
486
487    !verbose pop
488  !endif
489!macroend
490
491!macro CheckForFilesInUseCall _RESULT
492  !verbose push
493  !verbose ${_MOZFUNC_VERBOSE}
494  Call CheckForFilesInUse
495  Pop ${_RESULT}
496  !verbose pop
497!macroend
498
499!macro un.CheckForFilesInUseCall _RESULT
500  !verbose push
501  !verbose ${_MOZFUNC_VERBOSE}
502  Call un.CheckForFilesInUse
503  Pop ${_RESULT}
504  !verbose pop
505!macroend
506
507!macro un.CheckForFilesInUse
508  !ifndef un.CheckForFilesInUse
509    !verbose push
510    !verbose ${_MOZFUNC_VERBOSE}
511    !undef _MOZFUNC_UN
512    !define _MOZFUNC_UN "un."
513
514    !insertmacro CheckForFilesInUse
515
516    !undef _MOZFUNC_UN
517    !define _MOZFUNC_UN
518    !verbose pop
519  !endif
520!macroend
521
522/**
523 * The macros below will automatically prepend un. to the function names when
524 * they are defined (e.g. !define un.RegCleanMain).
525 */
526!verbose push
527!verbose 3
528!ifndef _MOZFUNC_VERBOSE
529  !define _MOZFUNC_VERBOSE 3
530!endif
531!verbose ${_MOZFUNC_VERBOSE}
532!define MOZFUNC_VERBOSE "!insertmacro MOZFUNC_VERBOSE"
533!define _MOZFUNC_UN
534!define _MOZFUNC_S
535!verbose pop
536
537!macro MOZFUNC_VERBOSE _VERBOSE
538  !verbose push
539  !verbose 3
540  !undef _MOZFUNC_VERBOSE
541  !define _MOZFUNC_VERBOSE ${_VERBOSE}
542  !verbose pop
543!macroend
544
545/**
546 * Displays a MessageBox and then calls abort to prevent continuing to the
547 * next page when the specified Window Class is found.
548 *
549 * @param   _WINDOW_CLASS
550 *          The Window Class to search for with FindWindow.
551 * @param   _MSG
552 *          The message text to display in the message box.
553 *
554 * $R7 = return value from FindWindow
555 * $R8 = _WINDOW_CLASS
556 * $R9 = _MSG
557 */
558!macro ManualCloseAppPrompt
559
560  !ifndef ${_MOZFUNC_UN}ManualCloseAppPrompt
561    !verbose push
562    !verbose ${_MOZFUNC_VERBOSE}
563    !define ${_MOZFUNC_UN}ManualCloseAppPrompt "!insertmacro ${_MOZFUNC_UN}ManualCloseAppPromptCall"
564
565    Function ${_MOZFUNC_UN}ManualCloseAppPrompt
566      Exch $R9
567      Exch 1
568      Exch $R8
569      Push $R7
570
571      FindWindow $R7 "$R8"
572      ${If} $R7 <> 0 ; integer comparison
573        MessageBox MB_OK|MB_ICONQUESTION "$R9"
574        Abort
575      ${EndIf}
576
577      Pop $R7
578      Exch $R8
579      Exch 1
580      Exch $R9
581    FunctionEnd
582
583    !verbose pop
584  !endif
585!macroend
586
587!macro ManualCloseAppPromptCall _WINDOW_CLASS _MSG
588  !verbose push
589  !verbose ${_MOZFUNC_VERBOSE}
590  Push "${_WINDOW_CLASS}"
591  Push "${_MSG}"
592  Call ManualCloseAppPrompt
593  !verbose pop
594!macroend
595
596!macro un.ManualCloseAppPromptCall _WINDOW_CLASS _MSG
597  !verbose push
598  !verbose ${_MOZFUNC_VERBOSE}
599  Push "${_WINDOW_CLASS}"
600  Push "${_MSG}"
601  Call un.ManualCloseAppPrompt
602  !verbose pop
603!macroend
604
605!macro un.ManualCloseAppPrompt
606  !ifndef un.ManualCloseAppPrompt
607    !verbose push
608    !verbose ${_MOZFUNC_VERBOSE}
609    !undef _MOZFUNC_UN
610    !define _MOZFUNC_UN "un."
611
612    !insertmacro ManualCloseAppPrompt
613
614    !undef _MOZFUNC_UN
615    !define _MOZFUNC_UN
616    !verbose pop
617  !endif
618!macroend
619
620
621################################################################################
622# Macros for working with the registry
623
624/**
625 * Writes a registry string using SHCTX and the supplied params and logs the
626 * action to the install log and the uninstall log if _LOG_UNINSTALL equals 1.
627 *
628 * Define NO_LOG to prevent all logging when calling this from the uninstaller.
629 *
630 * @param   _ROOT
631 *          The registry key root as defined by NSIS (e.g. HKLM, HKCU, etc.).
632 *          This will only be used for logging.
633 * @param   _KEY
634 *          The subkey in relation to the key root.
635 * @param   _NAME
636 *          The key value name to write to.
637 * @param   _STR
638 *          The string to write to the key value name.
639 * @param   _LOG_UNINSTALL
640 *          0 = don't add to uninstall log, 1 = add to uninstall log.
641 *
642 * $R5 = _ROOT
643 * $R6 = _KEY
644 * $R7 = _NAME
645 * $R8 = _STR
646 * $R9 = _LOG_UNINSTALL
647 */
648!macro WriteRegStr2
649
650  !ifndef ${_MOZFUNC_UN}WriteRegStr2
651    !verbose push
652    !verbose ${_MOZFUNC_VERBOSE}
653    !define ${_MOZFUNC_UN}WriteRegStr2 "!insertmacro ${_MOZFUNC_UN}WriteRegStr2Call"
654
655    Function ${_MOZFUNC_UN}WriteRegStr2
656      Exch $R9
657      Exch 1
658      Exch $R8
659      Exch 2
660      Exch $R7
661      Exch 3
662      Exch $R6
663      Exch 4
664      Exch $R5
665
666      ClearErrors
667      WriteRegStr SHCTX "$R6" "$R7" "$R8"
668
669      !ifndef NO_LOG
670        ${If} ${Errors}
671          ${LogMsg} "** ERROR Adding Registry String: $R5 | $R6 | $R7 | $R8 **"
672        ${Else}
673          ${If} $R9 == 1 ; add to the uninstall log?
674            ${LogUninstall} "RegVal: $R5 | $R6 | $R7"
675          ${EndIf}
676          ${LogMsg} "Added Registry String: $R5 | $R6 | $R7 | $R8"
677        ${EndIf}
678      !endif
679
680      Exch $R5
681      Exch 4
682      Exch $R6
683      Exch 3
684      Exch $R7
685      Exch 2
686      Exch $R8
687      Exch 1
688      Exch $R9
689    FunctionEnd
690
691    !verbose pop
692  !endif
693!macroend
694
695!macro WriteRegStr2Call _ROOT _KEY _NAME _STR _LOG_UNINSTALL
696  !verbose push
697  !verbose ${_MOZFUNC_VERBOSE}
698  Push "${_ROOT}"
699  Push "${_KEY}"
700  Push "${_NAME}"
701  Push "${_STR}"
702  Push "${_LOG_UNINSTALL}"
703  Call WriteRegStr2
704  !verbose pop
705!macroend
706
707!macro un.WriteRegStr2Call _ROOT _KEY _NAME _STR _LOG_UNINSTALL
708  !verbose push
709  !verbose ${_MOZFUNC_VERBOSE}
710  Push "${_ROOT}"
711  Push "${_KEY}"
712  Push "${_NAME}"
713  Push "${_STR}"
714  Push "${_LOG_UNINSTALL}"
715  Call un.WriteRegStr2
716  !verbose pop
717!macroend
718
719!macro un.WriteRegStr2
720  !ifndef un.WriteRegStr2
721    !verbose push
722    !verbose ${_MOZFUNC_VERBOSE}
723    !undef _MOZFUNC_UN
724    !define _MOZFUNC_UN "un."
725
726    !insertmacro WriteRegStr2
727
728    !undef _MOZFUNC_UN
729    !define _MOZFUNC_UN
730    !verbose pop
731  !endif
732!macroend
733
734/**
735 * Writes a registry dword using SHCTX and the supplied params and logs the
736 * action to the install log and the uninstall log if _LOG_UNINSTALL equals 1.
737 *
738 * Define NO_LOG to prevent all logging when calling this from the uninstaller.
739 *
740 * @param   _ROOT
741 *          The registry key root as defined by NSIS (e.g. HKLM, HKCU, etc.).
742 *          This will only be used for logging.
743 * @param   _KEY
744 *          The subkey in relation to the key root.
745 * @param   _NAME
746 *          The key value name to write to.
747 * @param   _DWORD
748 *          The dword to write to the key value name.
749 * @param   _LOG_UNINSTALL
750 *          0 = don't add to uninstall log, 1 = add to uninstall log.
751 *
752 * $R5 = _ROOT
753 * $R6 = _KEY
754 * $R7 = _NAME
755 * $R8 = _DWORD
756 * $R9 = _LOG_UNINSTALL
757 */
758!macro WriteRegDWORD2
759
760  !ifndef ${_MOZFUNC_UN}WriteRegDWORD2
761    !verbose push
762    !verbose ${_MOZFUNC_VERBOSE}
763    !define ${_MOZFUNC_UN}WriteRegDWORD2 "!insertmacro ${_MOZFUNC_UN}WriteRegDWORD2Call"
764
765    Function ${_MOZFUNC_UN}WriteRegDWORD2
766      Exch $R9
767      Exch 1
768      Exch $R8
769      Exch 2
770      Exch $R7
771      Exch 3
772      Exch $R6
773      Exch 4
774      Exch $R5
775
776      ClearErrors
777      WriteRegDWORD SHCTX "$R6" "$R7" "$R8"
778
779      !ifndef NO_LOG
780        ${If} ${Errors}
781          ${LogMsg} "** ERROR Adding Registry DWord: $R5 | $R6 | $R7 | $R8 **"
782        ${Else}
783          ${If} $R9 == 1 ; add to the uninstall log?
784            ${LogUninstall} "RegVal: $R5 | $R6 | $R7"
785          ${EndIf}
786          ${LogMsg} "Added Registry DWord: $R5 | $R6 | $R7 | $R8"
787        ${EndIf}
788      !endif
789
790      Exch $R5
791      Exch 4
792      Exch $R6
793      Exch 3
794      Exch $R7
795      Exch 2
796      Exch $R8
797      Exch 1
798      Exch $R9
799    FunctionEnd
800
801    !verbose pop
802  !endif
803!macroend
804
805!macro WriteRegDWORD2Call _ROOT _KEY _NAME _DWORD _LOG_UNINSTALL
806  !verbose push
807  !verbose ${_MOZFUNC_VERBOSE}
808  Push "${_ROOT}"
809  Push "${_KEY}"
810  Push "${_NAME}"
811  Push "${_DWORD}"
812  Push "${_LOG_UNINSTALL}"
813  Call WriteRegDWORD2
814  !verbose pop
815!macroend
816
817!macro un.WriteRegDWORD2Call _ROOT _KEY _NAME _DWORD _LOG_UNINSTALL
818  !verbose push
819  !verbose ${_MOZFUNC_VERBOSE}
820  Push "${_ROOT}"
821  Push "${_KEY}"
822  Push "${_NAME}"
823  Push "${_DWORD}"
824  Push "${_LOG_UNINSTALL}"
825  Call un.WriteRegDWORD2
826  !verbose pop
827!macroend
828
829!macro un.WriteRegDWORD2
830  !ifndef un.WriteRegDWORD2
831    !verbose push
832    !verbose ${_MOZFUNC_VERBOSE}
833    !undef _MOZFUNC_UN
834    !define _MOZFUNC_UN "un."
835
836    !insertmacro WriteRegDWORD2
837
838    !undef _MOZFUNC_UN
839    !define _MOZFUNC_UN
840    !verbose pop
841  !endif
842!macroend
843
844/**
845 * Writes a registry string to HKCR using the supplied params and logs the
846 * action to the install log and the uninstall log if _LOG_UNINSTALL equals 1.
847 *
848 * Define NO_LOG to prevent all logging when calling this from the uninstaller.
849 *
850 * @param   _ROOT
851 *          The registry key root as defined by NSIS (e.g. HKLM, HKCU, etc.).
852 *          This will only be used for logging.
853 * @param   _KEY
854 *          The subkey in relation to the key root.
855 * @param   _NAME
856 *          The key value name to write to.
857 * @param   _STR
858 *          The string to write to the key value name.
859 * @param   _LOG_UNINSTALL
860 *          0 = don't add to uninstall log, 1 = add to uninstall log.
861 *
862 * $R5 = _ROOT
863 * $R6 = _KEY
864 * $R7 = _NAME
865 * $R8 = _STR
866 * $R9 = _LOG_UNINSTALL
867 */
868!macro WriteRegStrHKCR
869
870  !ifndef ${_MOZFUNC_UN}WriteRegStrHKCR
871    !verbose push
872    !verbose ${_MOZFUNC_VERBOSE}
873    !define ${_MOZFUNC_UN}WriteRegStrHKCR "!insertmacro ${_MOZFUNC_UN}WriteRegStrHKCRCall"
874
875    Function ${_MOZFUNC_UN}WriteRegStrHKCR
876      Exch $R9
877      Exch 1
878      Exch $R8
879      Exch 2
880      Exch $R7
881      Exch 3
882      Exch $R6
883      Exch 4
884      Exch $R5
885
886      ClearErrors
887      WriteRegStr HKCR "$R6" "$R7" "$R8"
888
889      !ifndef NO_LOG
890        ${If} ${Errors}
891          ${LogMsg} "** ERROR Adding Registry String: $R5 | $R6 | $R7 | $R8 **"
892        ${Else}
893          ${If} $R9 == 1 ; add to the uninstall log?
894            ${LogUninstall} "RegVal: $R5 | $R6 | $R7"
895          ${EndIf}
896          ${LogMsg} "Added Registry String: $R5 | $R6 | $R7 | $R8"
897        ${EndIf}
898      !endif
899
900      Exch $R5
901      Exch 4
902      Exch $R6
903      Exch 3
904      Exch $R7
905      Exch 2
906      Exch $R8
907      Exch 1
908      Exch $R9
909    FunctionEnd
910
911    !verbose pop
912  !endif
913!macroend
914
915!macro WriteRegStrHKCRCall _ROOT _KEY _NAME _STR _LOG_UNINSTALL
916  !verbose push
917  !verbose ${_MOZFUNC_VERBOSE}
918  Push "${_ROOT}"
919  Push "${_KEY}"
920  Push "${_NAME}"
921  Push "${_STR}"
922  Push "${_LOG_UNINSTALL}"
923  Call WriteRegStrHKCR
924  !verbose pop
925!macroend
926
927!macro un.WriteRegStrHKCRCall _ROOT _KEY _NAME _STR _LOG_UNINSTALL
928  !verbose push
929  !verbose ${_MOZFUNC_VERBOSE}
930  Push "${_ROOT}"
931  Push "${_KEY}"
932  Push "${_NAME}"
933  Push "${_STR}"
934  Push "${_LOG_UNINSTALL}"
935  Call un.WriteRegStrHKCR
936  !verbose pop
937!macroend
938
939!macro un.WriteRegStrHKCR
940  !ifndef un.WriteRegStrHKCR
941    !verbose push
942    !verbose ${_MOZFUNC_VERBOSE}
943    !undef _MOZFUNC_UN
944    !define _MOZFUNC_UN "un."
945
946    !insertmacro WriteRegStrHKCR
947
948    !undef _MOZFUNC_UN
949    !define _MOZFUNC_UN
950    !verbose pop
951  !endif
952!macroend
953
954!ifndef KEY_SET_VALUE
955  !define KEY_SET_VALUE 0x0002
956!endif
957!ifndef KEY_WOW64_64KEY
958  !define KEY_WOW64_64KEY 0x0100
959!endif
960!ifndef HAVE_64BIT_BUILD
961  !define CREATE_KEY_SAM ${KEY_SET_VALUE}
962!else
963  !define CREATE_KEY_SAM ${KEY_SET_VALUE}|${KEY_WOW64_64KEY}
964!endif
965
966/**
967 * Creates a registry key. This will log the actions to the install and
968 * uninstall logs. Alternatively you can set a registry value to create the key
969 * and then delete the value.
970 *
971 * Define NO_LOG to prevent all logging when calling this from the uninstaller.
972 *
973 * @param   _ROOT
974 *          The registry key root as defined by NSIS (e.g. HKLM, HKCU, etc.).
975 * @param   _KEY
976 *          The subkey in relation to the key root.
977 * @param   _LOG_UNINSTALL
978 *          0 = don't add to uninstall log, 1 = add to uninstall log.
979 *
980 * $R4 = [out] handle to newly created registry key. If this is not a key
981 *       located in one of the predefined registry keys this must be closed
982 *       with RegCloseKey (this should not be needed unless someone decides to
983 *       do something extremely squirrelly with NSIS).
984 * $R5 = return value from RegCreateKeyExW (represented by R5 in the system call).
985 * $R6 = [in] hKey passed to RegCreateKeyExW.
986 * $R7 = _ROOT
987 * $R8 = _KEY
988 * $R9 = _LOG_UNINSTALL
989 */
990!macro CreateRegKey
991
992  !ifndef ${_MOZFUNC_UN}CreateRegKey
993    !verbose push
994    !verbose ${_MOZFUNC_VERBOSE}
995    !define ${_MOZFUNC_UN}CreateRegKey "!insertmacro ${_MOZFUNC_UN}CreateRegKeyCall"
996
997    Function ${_MOZFUNC_UN}CreateRegKey
998      Exch $R9
999      Exch 1
1000      Exch $R8
1001      Exch 2
1002      Exch $R7
1003      Push $R6
1004      Push $R5
1005      Push $R4
1006
1007      StrCmp $R7 "HKCR" +1 +2
1008      StrCpy $R6 "0x80000000"
1009      StrCmp $R7 "HKCU" +1 +2
1010      StrCpy $R6 "0x80000001"
1011      StrCmp $R7 "HKLM" +1 +2
1012      StrCpy $R6 "0x80000002"
1013
1014      ; see definition of RegCreateKey
1015      System::Call "Advapi32::RegCreateKeyExW(i R6, w R8, i 0, i 0, i 0,\
1016                                              i ${CREATE_KEY_SAM}, i 0, *i .R4,\
1017                                              i 0) i .R5"
1018
1019      !ifndef NO_LOG
1020        ; if $R5 is not 0 then there was an error creating the registry key.
1021        ${If} $R5 <> 0
1022          ${LogMsg} "** ERROR Adding Registry Key: $R7 | $R8 **"
1023        ${Else}
1024          ${If} $R9 == 1 ; add to the uninstall log?
1025            ${LogUninstall} "RegKey: $R7 | $R8"
1026          ${EndIf}
1027          ${LogMsg} "Added Registry Key: $R7 | $R8"
1028        ${EndIf}
1029      !endif
1030
1031      StrCmp $R5 0 +1 +2
1032      System::Call "Advapi32::RegCloseKey(iR4)"
1033
1034      Pop $R4
1035      Pop $R5
1036      Pop $R6
1037      Exch $R7
1038      Exch 2
1039      Exch $R8
1040      Exch 1
1041      Exch $R9
1042    FunctionEnd
1043
1044    !verbose pop
1045  !endif
1046!macroend
1047
1048!macro CreateRegKeyCall _ROOT _KEY _LOG_UNINSTALL
1049  !verbose push
1050  !verbose ${_MOZFUNC_VERBOSE}
1051  Push "${_ROOT}"
1052  Push "${_KEY}"
1053  Push "${_LOG_UNINSTALL}"
1054  Call CreateRegKey
1055  !verbose pop
1056!macroend
1057
1058!macro un.CreateRegKeyCall _ROOT _KEY _LOG_UNINSTALL
1059  !verbose push
1060  !verbose ${_MOZFUNC_VERBOSE}
1061  Push "${_ROOT}"
1062  Push "${_KEY}"
1063  Push "${_LOG_UNINSTALL}"
1064  Call un.CreateRegKey
1065  !verbose pop
1066!macroend
1067
1068!macro un.CreateRegKey
1069  !ifndef un.CreateRegKey
1070    !verbose push
1071    !verbose ${_MOZFUNC_VERBOSE}
1072    !undef _MOZFUNC_UN
1073    !define _MOZFUNC_UN "un."
1074
1075    !insertmacro CreateRegKey
1076
1077    !undef _MOZFUNC_UN
1078    !define _MOZFUNC_UN
1079    !verbose pop
1080  !endif
1081!macroend
1082
1083/**
1084 * Helper for checking for the existence of a registry key.
1085 * SHCTX is the root key to search.
1086 *
1087 * @param   _MAIN_KEY
1088 *          Sub key to iterate for the key in question
1089 * @param   _KEY
1090 *          Key name to search for
1091 * @return  _RESULT
1092 *          'true' / 'false' result
1093 */
1094!macro CheckIfRegistryKeyExists
1095  !ifndef CheckIfRegistryKeyExists
1096    !verbose push
1097    !verbose ${_MOZFUNC_VERBOSE}
1098    !define CheckIfRegistryKeyExists "!insertmacro CheckIfRegistryKeyExistsCall"
1099
1100    Function CheckIfRegistryKeyExists
1101      ; stack: main key, key
1102      Exch $R9 ; main key, stack: old R9, key
1103      Exch 1   ; stack: key, old R9
1104      Exch $R8 ; key, stack: old R8, old R9
1105      Push $R7
1106      Push $R6
1107      Push $R5
1108
1109      StrCpy $R5 "false"
1110      StrCpy $R7 "0" # loop index
1111      ${Do}
1112        EnumRegKey $R6 SHCTX "$R9" "$R7"
1113        ${If} "$R6" == "$R8"
1114          StrCpy $R5 "true"
1115          ${Break}
1116        ${EndIf}
1117        IntOp $R7 $R7 + 1
1118      ${LoopWhile} $R6 != ""
1119      ClearErrors
1120
1121      StrCpy $R9 $R5
1122
1123      Pop $R5
1124      Pop $R6
1125      Pop $R7 ; stack: old R8, old R9
1126      Pop $R8 ; stack: old R9
1127      Exch $R9 ; stack: result
1128    FunctionEnd
1129
1130    !verbose pop
1131  !endif
1132!macroend
1133
1134!macro CheckIfRegistryKeyExistsCall _MAIN_KEY _KEY _RESULT
1135  !verbose push
1136  !verbose ${_MOZFUNC_VERBOSE}
1137  Push "${_KEY}"
1138  Push "${_MAIN_KEY}"
1139  Call CheckIfRegistryKeyExists
1140  Pop ${_RESULT}
1141  !verbose pop
1142!macroend
1143
1144################################################################################
1145# Macros for adding file and protocol handlers
1146
1147/**
1148 * Writes common registry values for a handler using SHCTX.
1149 *
1150 * @param   _KEY
1151 *          The subkey in relation to the key root.
1152 * @param   _VALOPEN
1153 *          The path and args to launch the application.
1154 * @param   _VALICON
1155 *          The path to the binary that contains the icon group for the default icon
1156 *          followed by a comma and either the icon group's resource index or the icon
1157 *          group's resource id prefixed with a minus sign
1158 * @param   _DISPNAME
1159 *          The display name for the handler. If emtpy no value will be set.
1160 * @param   _ISPROTOCOL
1161 *          Sets protocol handler specific registry values when "true".
1162 *          Deletes protocol handler specific registry values when "delete".
1163 *          Otherwise doesn't touch handler specific registry values.
1164 * @param   _ISDDE
1165 *          Sets DDE specific registry values when "true".
1166 *
1167 * $R3 = string value of the current registry key path.
1168 * $R4 = _KEY
1169 * $R5 = _VALOPEN
1170 * $R6 = _VALICON
1171 * $R7 = _DISPNAME
1172 * $R8 = _ISPROTOCOL
1173 * $R9 = _ISDDE
1174 */
1175!macro AddHandlerValues
1176
1177  !ifndef ${_MOZFUNC_UN}AddHandlerValues
1178    !verbose push
1179    !verbose ${_MOZFUNC_VERBOSE}
1180    !define ${_MOZFUNC_UN}AddHandlerValues "!insertmacro ${_MOZFUNC_UN}AddHandlerValuesCall"
1181
1182    Function ${_MOZFUNC_UN}AddHandlerValues
1183      Exch $R9
1184      Exch 1
1185      Exch $R8
1186      Exch 2
1187      Exch $R7
1188      Exch 3
1189      Exch $R6
1190      Exch 4
1191      Exch $R5
1192      Exch 5
1193      Exch $R4
1194      Push $R3
1195
1196      StrCmp "$R7" "" +6 +1
1197      ReadRegStr $R3 SHCTX "$R4" "FriendlyTypeName"
1198
1199      StrCmp "$R3" "" +1 +3
1200      WriteRegStr SHCTX "$R4" "" "$R7"
1201      WriteRegStr SHCTX "$R4" "FriendlyTypeName" "$R7"
1202
1203      StrCmp "$R8" "true" +1 +2
1204      WriteRegStr SHCTX "$R4" "URL Protocol" ""
1205      StrCmp "$R8" "delete" +1 +2
1206      DeleteRegValue SHCTX "$R4" "URL Protocol"
1207      StrCpy $R3 ""
1208      ReadRegDWord $R3 SHCTX "$R4" "EditFlags"
1209      StrCmp $R3 "" +1 +3  ; Only add EditFlags if a value doesn't exist
1210      DeleteRegValue SHCTX "$R4" "EditFlags"
1211      WriteRegDWord SHCTX "$R4" "EditFlags" 0x00000002
1212
1213      StrCmp "$R6" "" +2 +1
1214      WriteRegStr SHCTX "$R4\DefaultIcon" "" "$R6"
1215
1216      StrCmp "$R5" "" +2 +1
1217      WriteRegStr SHCTX "$R4\shell\open\command" "" "$R5"
1218
1219!ifdef DDEApplication
1220      StrCmp "$R9" "true" +1 +11
1221      WriteRegStr SHCTX "$R4\shell\open\ddeexec" "" "$\"%1$\",,0,0,,,,"
1222      WriteRegStr SHCTX "$R4\shell\open\ddeexec" "NoActivateHandler" ""
1223      WriteRegStr SHCTX "$R4\shell\open\ddeexec\Application" "" "${DDEApplication}"
1224      WriteRegStr SHCTX "$R4\shell\open\ddeexec\Topic" "" "WWW_OpenURL"
1225      ; The ifexec key may have been added by another application so try to
1226      ; delete it to prevent it from breaking this app's shell integration.
1227      ; Also, IE 6 and below doesn't remove this key when it sets itself as the
1228      ; default handler and if this key exists IE's shell integration breaks.
1229      DeleteRegKey HKLM "$R4\shell\open\ddeexec\ifexec"
1230      DeleteRegKey HKCU "$R4\shell\open\ddeexec\ifexec"
1231!endif
1232
1233      ClearErrors
1234
1235      Pop $R3
1236      Exch $R4
1237      Exch 5
1238      Exch $R5
1239      Exch 4
1240      Exch $R6
1241      Exch 3
1242      Exch $R7
1243      Exch 2
1244      Exch $R8
1245      Exch 1
1246      Exch $R9
1247    FunctionEnd
1248
1249    !verbose pop
1250  !endif
1251!macroend
1252
1253!macro AddHandlerValuesCall _KEY _VALOPEN _VALICON _DISPNAME _ISPROTOCOL _ISDDE
1254  !verbose push
1255  !verbose ${_MOZFUNC_VERBOSE}
1256  Push "${_KEY}"
1257  Push "${_VALOPEN}"
1258  Push "${_VALICON}"
1259  Push "${_DISPNAME}"
1260  Push "${_ISPROTOCOL}"
1261  Push "${_ISDDE}"
1262  Call AddHandlerValues
1263  !verbose pop
1264!macroend
1265
1266!macro un.AddHandlerValuesCall _KEY _VALOPEN _VALICON _DISPNAME _ISPROTOCOL _ISDDE
1267  !verbose push
1268  !verbose ${_MOZFUNC_VERBOSE}
1269  Push "${_KEY}"
1270  Push "${_VALOPEN}"
1271  Push "${_VALICON}"
1272  Push "${_DISPNAME}"
1273  Push "${_ISPROTOCOL}"
1274  Push "${_ISDDE}"
1275  Call un.AddHandlerValues
1276  !verbose pop
1277!macroend
1278
1279!macro un.AddHandlerValues
1280  !ifndef un.AddHandlerValues
1281    !verbose push
1282    !verbose ${_MOZFUNC_VERBOSE}
1283    !undef _MOZFUNC_UN
1284    !define _MOZFUNC_UN "un."
1285
1286    !insertmacro AddHandlerValues
1287
1288    !undef _MOZFUNC_UN
1289    !define _MOZFUNC_UN
1290    !verbose pop
1291  !endif
1292!macroend
1293
1294/**
1295 * Writes common registry values for a handler that uses DDE using SHCTX.
1296 *
1297 * @param   _KEY
1298 *          The key name in relation to the HKCR root. SOFTWARE\Classes is
1299 *          prefixed to this value when using SHCTX.
1300 * @param   _VALOPEN
1301 *          The path and args to launch the application.
1302 * @param   _VALICON
1303 *          The path to the binary that contains the icon group for the default icon
1304 *          followed by a comma and either the icon group's resource index or the icon
1305 *          group's resource id prefixed with a minus sign
1306 * @param   _DISPNAME
1307 *          The display name for the handler. If emtpy no value will be set.
1308 * @param   _ISPROTOCOL
1309 *          Sets protocol handler specific registry values when "true".
1310 *          Deletes protocol handler specific registry values when "delete".
1311 *          Otherwise doesn't touch handler specific registry values.
1312 * @param   _DDE_APPNAME
1313 *          Sets DDE specific registry values when not an empty string.
1314 *
1315 * $R0 = storage for SOFTWARE\Classes
1316 * $R1 = string value of the current registry key path.
1317 * $R2 = _KEY
1318 * $R3 = _VALOPEN
1319 * $R4 = _VALICON
1320 * $R5 = _DISPNAME
1321 * $R6 = _ISPROTOCOL
1322 * $R7 = _DDE_APPNAME
1323 * $R8 = _DDE_DEFAULT
1324 * $R9 = _DDE_TOPIC
1325 */
1326!macro AddDDEHandlerValues
1327
1328  !ifndef ${_MOZFUNC_UN}AddDDEHandlerValues
1329    !verbose push
1330    !verbose ${_MOZFUNC_VERBOSE}
1331    !define ${_MOZFUNC_UN}AddDDEHandlerValues "!insertmacro ${_MOZFUNC_UN}AddDDEHandlerValuesCall"
1332
1333    Function ${_MOZFUNC_UN}AddDDEHandlerValues
1334      Exch $R9
1335      Exch 1
1336      Exch $R8
1337      Exch 2
1338      Exch $R7
1339      Exch 3
1340      Exch $R6
1341      Exch 4
1342      Exch $R5
1343      Exch 5
1344      Exch $R4
1345      Exch 6
1346      Exch $R3
1347      Exch 7
1348      Exch $R2
1349      Push $R1
1350      Push $R0
1351
1352      StrCpy $R0 "SOFTWARE\Classes"
1353      StrCmp "$R5" "" +6 +1
1354      ReadRegStr $R1 SHCTX "$R2" "FriendlyTypeName"
1355
1356      StrCmp "$R1" "" +1 +3
1357      WriteRegStr SHCTX "$R0\$R2" "" "$R5"
1358      WriteRegStr SHCTX "$R0\$R2" "FriendlyTypeName" "$R5"
1359
1360      StrCmp "$R6" "true" +1 +2
1361      WriteRegStr SHCTX "$R0\$R2" "URL Protocol" ""
1362      StrCmp "$R6" "delete" +1 +2
1363      DeleteRegValue SHCTX "$R0\$R2" "URL Protocol"
1364      StrCpy $R1 ""
1365      ReadRegDWord $R1 SHCTX "$R0\$R2" "EditFlags"
1366      StrCmp $R1 "" +1 +3  ; Only add EditFlags if a value doesn't exist
1367      DeleteRegValue SHCTX "$R0\$R2" "EditFlags"
1368      WriteRegDWord SHCTX "$R0\$R2" "EditFlags" 0x00000002
1369
1370      StrCmp "$R4" "" +2 +1
1371      WriteRegStr SHCTX "$R0\$R2\DefaultIcon" "" "$R4"
1372
1373      WriteRegStr SHCTX "$R0\$R2\shell" "" "open"
1374      WriteRegStr SHCTX "$R0\$R2\shell\open\command" "" "$R3"
1375
1376      WriteRegStr SHCTX "$R0\$R2\shell\open\ddeexec" "" "$R8"
1377      WriteRegStr SHCTX "$R0\$R2\shell\open\ddeexec" "NoActivateHandler" ""
1378      WriteRegStr SHCTX "$R0\$R2\shell\open\ddeexec\Application" "" "$R7"
1379      WriteRegStr SHCTX "$R0\$R2\shell\open\ddeexec\Topic" "" "$R9"
1380
1381      ; The ifexec key may have been added by another application so try to
1382      ; delete it to prevent it from breaking this app's shell integration.
1383      ; Also, IE 6 and below doesn't remove this key when it sets itself as the
1384      ; default handler and if this key exists IE's shell integration breaks.
1385      DeleteRegKey HKLM "$R0\$R2\shell\open\ddeexec\ifexec"
1386      DeleteRegKey HKCU "$R0\$R2\shell\open\ddeexec\ifexec"
1387      ClearErrors
1388
1389      Pop $R0
1390      Pop $R1
1391      Exch $R2
1392      Exch 7
1393      Exch $R3
1394      Exch 6
1395      Exch $R4
1396      Exch 5
1397      Exch $R5
1398      Exch 4
1399      Exch $R6
1400      Exch 3
1401      Exch $R7
1402      Exch 2
1403      Exch $R8
1404      Exch 1
1405      Exch $R9
1406    FunctionEnd
1407
1408    !verbose pop
1409  !endif
1410!macroend
1411
1412!macro AddDDEHandlerValuesCall _KEY _VALOPEN _VALICON _DISPNAME _ISPROTOCOL _DDE_APPNAME _DDE_DEFAULT _DDE_TOPIC
1413  !verbose push
1414  !verbose ${_MOZFUNC_VERBOSE}
1415  Push "${_KEY}"
1416  Push "${_VALOPEN}"
1417  Push "${_VALICON}"
1418  Push "${_DISPNAME}"
1419  Push "${_ISPROTOCOL}"
1420  Push "${_DDE_APPNAME}"
1421  Push "${_DDE_DEFAULT}"
1422  Push "${_DDE_TOPIC}"
1423  Call AddDDEHandlerValues
1424  !verbose pop
1425!macroend
1426
1427!macro un.AddDDEHandlerValuesCall _KEY _VALOPEN _VALICON _DISPNAME _ISPROTOCOL _DDE_APPNAME _DDE_DEFAULT _DDE_TOPIC
1428  !verbose push
1429  !verbose ${_MOZFUNC_VERBOSE}
1430  Push "${_KEY}"
1431  Push "${_VALOPEN}"
1432  Push "${_VALICON}"
1433  Push "${_DISPNAME}"
1434  Push "${_ISPROTOCOL}"
1435  Push "${_DDE_APPNAME}"
1436  Push "${_DDE_DEFAULT}"
1437  Push "${_DDE_TOPIC}"
1438  Call un.AddDDEHandlerValues
1439  !verbose pop
1440!macroend
1441
1442!macro un.AddDDEHandlerValues
1443  !ifndef un.AddDDEHandlerValues
1444    !verbose push
1445    !verbose ${_MOZFUNC_VERBOSE}
1446    !undef _MOZFUNC_UN
1447    !define _MOZFUNC_UN "un."
1448
1449    !insertmacro AddDDEHandlerValues
1450
1451    !undef _MOZFUNC_UN
1452    !define _MOZFUNC_UN
1453    !verbose pop
1454  !endif
1455!macroend
1456
1457/**
1458 * Writes common registry values for a handler that DOES NOT use DDE using SHCTX.
1459 *
1460 * @param   _KEY
1461 *          The key name in relation to the HKCR root. SOFTWARE\Classes is
1462 *          prefixed to this value when using SHCTX.
1463 * @param   _VALOPEN
1464 *          The path and args to launch the application.
1465 * @param   _VALICON
1466 *          The path to the binary that contains the icon group for the default icon
1467 *          followed by a comma and either the icon group's resource index or the icon
1468 *          group's resource id prefixed with a minus sign
1469 * @param   _DISPNAME
1470 *          The display name for the handler. If emtpy no value will be set.
1471 * @param   _ISPROTOCOL
1472 *          Sets protocol handler specific registry values when "true".
1473 *          Deletes protocol handler specific registry values when "delete".
1474 *          Otherwise doesn't touch handler specific registry values.
1475 *
1476 * $R3 = storage for SOFTWARE\Classes
1477 * $R4 = string value of the current registry key path.
1478 * $R5 = _KEY
1479 * $R6 = _VALOPEN
1480 * $R7 = _VALICON
1481 * $R8 = _DISPNAME
1482 * $R9 = _ISPROTOCOL
1483 */
1484!macro AddDisabledDDEHandlerValues
1485
1486  !ifndef ${_MOZFUNC_UN}AddDisabledDDEHandlerValues
1487    !verbose push
1488    !verbose ${_MOZFUNC_VERBOSE}
1489    !define ${_MOZFUNC_UN}AddDisabledDDEHandlerValues "!insertmacro ${_MOZFUNC_UN}AddDisabledDDEHandlerValuesCall"
1490
1491    Function ${_MOZFUNC_UN}AddDisabledDDEHandlerValues
1492      Exch $R9 ; _ISPROTOCOL
1493      Exch 1
1494      Exch $R8 ; FriendlyTypeName
1495      Exch 2
1496      Exch $R7 ; icon index
1497      Exch 3
1498      Exch $R6 ; shell\open\command
1499      Exch 4
1500      Exch $R5 ; reg key
1501      Push $R4 ;
1502      Push $R3 ; base reg class
1503
1504      StrCpy $R3 "SOFTWARE\Classes"
1505      StrCmp "$R8" "" +6 +1
1506      ReadRegStr $R4 SHCTX "$R5" "FriendlyTypeName"
1507
1508      StrCmp "$R4" "" +1 +3
1509      WriteRegStr SHCTX "$R3\$R5" "" "$R8"
1510      WriteRegStr SHCTX "$R3\$R5" "FriendlyTypeName" "$R8"
1511
1512      StrCmp "$R9" "true" +1 +2
1513      WriteRegStr SHCTX "$R3\$R5" "URL Protocol" ""
1514      StrCmp "$R9" "delete" +1 +2
1515      DeleteRegValue SHCTX "$R3\$R5" "URL Protocol"
1516      StrCpy $R4 ""
1517      ReadRegDWord $R4 SHCTX "$R3\$R5" "EditFlags"
1518      StrCmp $R4 "" +1 +3  ; Only add EditFlags if a value doesn't exist
1519      DeleteRegValue SHCTX "$R3\$R5" "EditFlags"
1520      WriteRegDWord SHCTX "$R3\$R5" "EditFlags" 0x00000002
1521
1522      StrCmp "$R7" "" +2 +1
1523      WriteRegStr SHCTX "$R3\$R5\DefaultIcon" "" "$R7"
1524
1525      ; Main command handler for the app
1526      WriteRegStr SHCTX "$R3\$R5\shell" "" "open"
1527      WriteRegStr SHCTX "$R3\$R5\shell\open\command" "" "$R6"
1528
1529      ; Drop support for DDE (bug 491947), and remove old dde entries if
1530      ; they exist.
1531      ;
1532      ; Note, changes in SHCTX should propegate to hkey classes root when
1533      ; current user or local machine entries are written. Windows will also
1534      ; attempt to propegate entries when a handler is used. CR entries are a
1535      ; combination of LM and CU, with CU taking priority.
1536      ;
1537      ; To disable dde, an empty shell/ddeexec key must be created in current
1538      ; user or local machine. Unfortunately, settings have various different
1539      ; behaviors depending on the windows version. The following code attempts
1540      ; to address these differences.
1541      ;
1542      ; On XP (no SP, SP1, SP2), Vista: An empty default string
1543      ; must be set under ddeexec. Empty strings propagate to CR.
1544      ;
1545      ; Win7: IE does not configure ddeexec, so issues with left over ddeexec keys
1546      ; in LM are reduced. We configure an empty ddeexec key with an empty default
1547      ; string in CU to be sure.
1548      ;
1549      DeleteRegKey SHCTX "SOFTWARE\Classes\$R5\shell\open\ddeexec"
1550      WriteRegStr SHCTX "SOFTWARE\Classes\$R5\shell\open\ddeexec" "" ""
1551
1552      ClearErrors
1553
1554      Pop $R3
1555      Pop $R4
1556      Exch $R5
1557      Exch 4
1558      Exch $R6
1559      Exch 3
1560      Exch $R7
1561      Exch 2
1562      Exch $R8
1563      Exch 1
1564      Exch $R9
1565    FunctionEnd
1566
1567    !verbose pop
1568  !endif
1569!macroend
1570
1571!macro AddDisabledDDEHandlerValuesCall _KEY _VALOPEN _VALICON _DISPNAME _ISPROTOCOL
1572  !verbose push
1573  !verbose ${_MOZFUNC_VERBOSE}
1574  Push "${_KEY}"
1575  Push "${_VALOPEN}"
1576  Push "${_VALICON}"
1577  Push "${_DISPNAME}"
1578  Push "${_ISPROTOCOL}"
1579  Call AddDisabledDDEHandlerValues
1580  !verbose pop
1581!macroend
1582
1583!macro un.AddDisabledDDEHandlerValuesCall _KEY _VALOPEN _VALICON _DISPNAME _ISPROTOCOL
1584  !verbose push
1585  !verbose ${_MOZFUNC_VERBOSE}
1586  Push "${_KEY}"
1587  Push "${_VALOPEN}"
1588  Push "${_VALICON}"
1589  Push "${_DISPNAME}"
1590  Push "${_ISPROTOCOL}"
1591  Call un.AddDisabledDDEHandlerValues
1592  !verbose pop
1593!macroend
1594
1595!macro un.AddDisabledDDEHandlerValues
1596  !ifndef un.AddDisabledDDEHandlerValues
1597    !verbose push
1598    !verbose ${_MOZFUNC_VERBOSE}
1599    !undef _MOZFUNC_UN
1600    !define _MOZFUNC_UN "un."
1601
1602    !insertmacro AddDisabledDDEHandlerValues
1603
1604    !undef _MOZFUNC_UN
1605    !define _MOZFUNC_UN
1606    !verbose pop
1607  !endif
1608!macroend
1609
1610
1611################################################################################
1612# Macros for handling DLL registration
1613
1614!macro RegisterDLL DLL
1615
1616  ; The x64 regsvr32.exe registers x86 DLL's properly on Windows Vista and above
1617  ; (not on Windows XP http://support.microsoft.com/kb/282747) so just use it
1618  ; when installing on an x64 systems even when installing an x86 application.
1619  ${If} ${RunningX64}
1620    ${DisableX64FSRedirection}
1621    ExecWait '"$SYSDIR\regsvr32.exe" /s "${DLL}"'
1622    ${EnableX64FSRedirection}
1623  ${Else}
1624    RegDLL "${DLL}"
1625  ${EndIf}
1626
1627!macroend
1628
1629!macro UnregisterDLL DLL
1630
1631  ; The x64 regsvr32.exe registers x86 DLL's properly on Windows Vista and above
1632  ; (not on Windows XP http://support.microsoft.com/kb/282747) so just use it
1633  ; when installing on an x64 systems even when installing an x86 application.
1634  ${If} ${RunningX64}
1635    ${DisableX64FSRedirection}
1636    ExecWait '"$SYSDIR\regsvr32.exe" /s /u "${DLL}"'
1637    ${EnableX64FSRedirection}
1638  ${Else}
1639    UnRegDLL "${DLL}"
1640  ${EndIf}
1641
1642!macroend
1643
1644!define RegisterDLL "!insertmacro RegisterDLL"
1645!define UnregisterDLL "!insertmacro UnregisterDLL"
1646
1647
1648################################################################################
1649# Macros for retrieving existing install paths
1650
1651/**
1652 * Finds a second installation of the application so we can make informed
1653 * decisions about registry operations. This uses SHCTX to determine the
1654 * registry hive so you must call SetShellVarContext first.
1655 *
1656 * @param   _KEY
1657 *          The registry subkey (typically this will be Software\Mozilla).
1658 * @return  _RESULT
1659 *          false if a second install isn't found, path to the main exe if a
1660 *          second install is found.
1661 *
1662 * $R3 = stores the long path to $INSTDIR
1663 * $R4 = counter for the outer loop's EnumRegKey
1664 * $R5 = return value from ReadRegStr and RemoveQuotesFromPath
1665 * $R6 = return value from GetParent
1666 * $R7 = return value from the loop's EnumRegKey
1667 * $R8 = storage for _KEY
1668 * $R9 = _KEY and _RESULT
1669 */
1670!macro GetSecondInstallPath
1671
1672  !ifndef ${_MOZFUNC_UN}GetSecondInstallPath
1673    !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN}
1674    !insertmacro ${_MOZFUNC_UN_TMP}GetLongPath
1675    !insertmacro ${_MOZFUNC_UN_TMP}GetParent
1676    !insertmacro ${_MOZFUNC_UN_TMP}RemoveQuotesFromPath
1677    !undef _MOZFUNC_UN
1678    !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP}
1679    !undef _MOZFUNC_UN_TMP
1680
1681    !verbose push
1682    !verbose ${_MOZFUNC_VERBOSE}
1683    !define ${_MOZFUNC_UN}GetSecondInstallPath "!insertmacro ${_MOZFUNC_UN}GetSecondInstallPathCall"
1684
1685    Function ${_MOZFUNC_UN}GetSecondInstallPath
1686      Exch $R9
1687      Push $R8
1688      Push $R7
1689      Push $R6
1690      Push $R5
1691      Push $R4
1692      Push $R3
1693
1694      ${${_MOZFUNC_UN}GetLongPath} "$INSTDIR" $R3
1695
1696      StrCpy $R4 0       ; set the counter for the loop to 0
1697      StrCpy $R8 "$R9"   ; Registry key path to search
1698      StrCpy $R9 "false" ; default return value
1699
1700      loop:
1701      EnumRegKey $R7 SHCTX $R8 $R4
1702      StrCmp $R7 "" end +1  ; if empty there are no more keys to enumerate
1703      IntOp $R4 $R4 + 1     ; increment the loop's counter
1704      ClearErrors
1705      ReadRegStr $R5 SHCTX "$R8\$R7\bin" "PathToExe"
1706      IfErrors loop
1707
1708      ${${_MOZFUNC_UN}RemoveQuotesFromPath} "$R5" $R5
1709
1710      IfFileExists "$R5" +1 loop
1711      ${${_MOZFUNC_UN}GetLongPath} "$R5" $R5
1712      ${${_MOZFUNC_UN}GetParent} "$R5" $R6
1713      StrCmp "$R6" "$R3" loop +1
1714      StrCmp "$R6\${FileMainEXE}" "$R5" +1 loop
1715      StrCpy $R9 "$R5"
1716
1717      end:
1718      ClearErrors
1719
1720      Pop $R3
1721      Pop $R4
1722      Pop $R5
1723      Pop $R6
1724      Pop $R7
1725      Pop $R8
1726      Exch $R9
1727    FunctionEnd
1728
1729    !verbose pop
1730  !endif
1731!macroend
1732
1733!macro GetSecondInstallPathCall _KEY _RESULT
1734  !verbose push
1735  !verbose ${_MOZFUNC_VERBOSE}
1736  Push "${_KEY}"
1737  Call GetSecondInstallPath
1738  Pop ${_RESULT}
1739  !verbose pop
1740!macroend
1741
1742!macro un.GetSecondInstallPathCall _KEY _RESULT
1743  !verbose push
1744  !verbose ${_MOZFUNC_VERBOSE}
1745  Push "${_KEY}"
1746  Call un.GetSecondInstallPath
1747  Pop ${_RESULT}
1748  !verbose pop
1749!macroend
1750
1751!macro un.GetSecondInstallPath
1752  !ifndef un.GetSecondInstallPath
1753    !verbose push
1754    !verbose ${_MOZFUNC_VERBOSE}
1755    !undef _MOZFUNC_UN
1756    !define _MOZFUNC_UN "un."
1757
1758    !insertmacro GetSecondInstallPath
1759
1760    !undef _MOZFUNC_UN
1761    !define _MOZFUNC_UN
1762    !verbose pop
1763  !endif
1764!macroend
1765
1766/**
1767 * Finds an existing installation path for the application based on the
1768 * application's executable name so we can default to using this path for the
1769 * install. If there is zero or more than one installation of the application
1770 * then we default to the default installation path. This uses SHCTX to
1771 * determine the registry hive to read from so you must call SetShellVarContext
1772 * first.
1773 *
1774 * @param   _KEY
1775 *          The registry subkey (typically this will be Software\Mozilla\App Name).
1776 * @return  _RESULT
1777 *          false if a single install location for this app name isn't found,
1778 *          path to the install directory if a single install location is found.
1779 *
1780 * $R5 = counter for the loop's EnumRegKey
1781 * $R6 = return value from EnumRegKey
1782 * $R7 = return value from ReadRegStr
1783 * $R8 = storage for _KEY
1784 * $R9 = _KEY and _RESULT
1785 */
1786!macro GetSingleInstallPath
1787
1788  !ifndef ${_MOZFUNC_UN}GetSingleInstallPath
1789    !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN}
1790    !insertmacro ${_MOZFUNC_UN_TMP}GetLongPath
1791    !insertmacro ${_MOZFUNC_UN_TMP}GetParent
1792    !insertmacro ${_MOZFUNC_UN_TMP}RemoveQuotesFromPath
1793    !undef _MOZFUNC_UN
1794    !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP}
1795    !undef _MOZFUNC_UN_TMP
1796
1797    !verbose push
1798    !verbose ${_MOZFUNC_VERBOSE}
1799    !define ${_MOZFUNC_UN}GetSingleInstallPath "!insertmacro ${_MOZFUNC_UN}GetSingleInstallPathCall"
1800
1801    Function ${_MOZFUNC_UN}GetSingleInstallPath
1802      Exch $R9
1803      Push $R8
1804      Push $R7
1805      Push $R6
1806      Push $R5
1807
1808      StrCpy $R8 $R9
1809      StrCpy $R9 "false"
1810      StrCpy $R5 0  ; set the counter for the loop to 0
1811
1812      loop:
1813      ClearErrors
1814      EnumRegKey $R6 SHCTX $R8 $R5
1815      IfErrors cleanup
1816      StrCmp $R6 "" cleanup +1  ; if empty there are no more keys to enumerate
1817      IntOp $R5 $R5 + 1         ; increment the loop's counter
1818      ClearErrors
1819      ReadRegStr $R7 SHCTX "$R8\$R6\Main" "PathToExe"
1820      IfErrors loop
1821      ${${_MOZFUNC_UN}RemoveQuotesFromPath} "$R7" $R7
1822      GetFullPathName $R7 "$R7"
1823      IfErrors loop
1824
1825      StrCmp "$R9" "false" +1 +3
1826      StrCpy $R9 "$R7"
1827      GoTo Loop
1828
1829      StrCpy $R9 "false"
1830
1831      cleanup:
1832      StrCmp $R9 "false" end +1
1833      ${${_MOZFUNC_UN}GetLongPath} "$R9" $R9
1834      ${${_MOZFUNC_UN}GetParent} "$R9" $R9
1835
1836      end:
1837      ClearErrors
1838
1839      Pop $R5
1840      Pop $R6
1841      Pop $R7
1842      Pop $R8
1843      Exch $R9
1844    FunctionEnd
1845
1846    !verbose pop
1847  !endif
1848!macroend
1849
1850!macro GetSingleInstallPathCall _KEY _RESULT
1851  !verbose push
1852  !verbose ${_MOZFUNC_VERBOSE}
1853  Push "${_KEY}"
1854  Call GetSingleInstallPath
1855  Pop ${_RESULT}
1856  !verbose pop
1857!macroend
1858
1859!macro un.GetSingleInstallPathCall _KEY _RESULT
1860  !verbose push
1861  !verbose ${_MOZFUNC_VERBOSE}
1862  Push "${_KEY}"
1863  Call un.GetSingleInstallPath
1864  Pop ${_RESULT}
1865  !verbose pop
1866!macroend
1867
1868!macro un.GetSingleInstallPath
1869  !ifndef un.GetSingleInstallPath
1870    !verbose push
1871    !verbose ${_MOZFUNC_VERBOSE}
1872    !undef _MOZFUNC_UN
1873    !define _MOZFUNC_UN "un."
1874
1875    !insertmacro GetSingleInstallPath
1876
1877    !undef _MOZFUNC_UN
1878    !define _MOZFUNC_UN
1879    !verbose pop
1880  !endif
1881!macroend
1882
1883
1884################################################################################
1885# Macros for working with the file system
1886
1887/**
1888 * Attempts to delete a file if it exists. This will fail if the file is in use.
1889 *
1890 * @param   _FILE
1891 *          The path to the file that is to be deleted.
1892 */
1893!macro DeleteFile _FILE
1894  ${If} ${FileExists} "${_FILE}"
1895    Delete "${_FILE}"
1896  ${EndIf}
1897!macroend
1898!define DeleteFile "!insertmacro DeleteFile"
1899
1900/**
1901 * Removes a directory if it exists and is empty.
1902 *
1903 * @param   _DIR
1904 *          The path to the directory that is to be removed.
1905 */
1906!macro RemoveDir _DIR
1907  ${If} ${FileExists} "${_DIR}"
1908    RmDir "${_DIR}"
1909  ${EndIf}
1910!macroend
1911!define RemoveDir "!insertmacro RemoveDir"
1912
1913/**
1914 * Checks whether it is possible to create and delete a directory and a file in
1915 * the install directory. Creation and deletion of files and directories are
1916 * checked since a user may have rights for one and not the other. If creation
1917 * and deletion of a file and a directory are successful this macro will return
1918 * true... if not, this it return false.
1919 *
1920 * @return  _RESULT
1921 *          true if files and directories can be created and deleted in the
1922 *          install directory otherwise false.
1923 *
1924 * $R8 = temporary filename in the installation directory returned from
1925 *       GetTempFileName.
1926 * $R9 = _RESULT
1927 */
1928!macro CanWriteToInstallDir
1929
1930  !ifndef ${_MOZFUNC_UN}CanWriteToInstallDir
1931    !verbose push
1932    !verbose ${_MOZFUNC_VERBOSE}
1933    !define ${_MOZFUNC_UN}CanWriteToInstallDir "!insertmacro ${_MOZFUNC_UN}CanWriteToInstallDirCall"
1934
1935    Function ${_MOZFUNC_UN}CanWriteToInstallDir
1936      Push $R9
1937      Push $R8
1938
1939      StrCpy $R9 "true"
1940
1941      ; IfFileExists returns false for $INSTDIR when $INSTDIR is the root of a
1942      ; UNC path so always try to create $INSTDIR
1943      CreateDirectory "$INSTDIR\"
1944      GetTempFileName $R8 "$INSTDIR\"
1945
1946      ${Unless} ${FileExists} $R8 ; Can files be created?
1947        StrCpy $R9 "false"
1948        Goto done
1949      ${EndUnless}
1950
1951      Delete $R8
1952      ${If} ${FileExists} $R8 ; Can files be deleted?
1953        StrCpy $R9 "false"
1954        Goto done
1955      ${EndIf}
1956
1957      CreateDirectory $R8
1958      ${Unless} ${FileExists} $R8  ; Can directories be created?
1959        StrCpy $R9 "false"
1960        Goto done
1961      ${EndUnless}
1962
1963      RmDir $R8
1964      ${If} ${FileExists} $R8  ; Can directories be deleted?
1965        StrCpy $R9 "false"
1966        Goto done
1967      ${EndIf}
1968
1969      done:
1970
1971      RmDir "$INSTDIR\" ; Only remove $INSTDIR if it is empty
1972      ClearErrors
1973
1974      Pop $R8
1975      Exch $R9
1976    FunctionEnd
1977
1978    !verbose pop
1979  !endif
1980!macroend
1981
1982!macro CanWriteToInstallDirCall _RESULT
1983  !verbose push
1984  !verbose ${_MOZFUNC_VERBOSE}
1985  Call CanWriteToInstallDir
1986  Pop ${_RESULT}
1987  !verbose pop
1988!macroend
1989
1990!macro un.CanWriteToInstallDirCall _RESULT
1991  !verbose push
1992  !verbose ${_MOZFUNC_VERBOSE}
1993  Call un.CanWriteToInstallDir
1994  Pop ${_RESULT}
1995  !verbose pop
1996!macroend
1997
1998!macro un.CanWriteToInstallDir
1999  !ifndef un.CanWriteToInstallDir
2000    !verbose push
2001    !verbose ${_MOZFUNC_VERBOSE}
2002    !undef _MOZFUNC_UN
2003    !define _MOZFUNC_UN "un."
2004
2005    !insertmacro CanWriteToInstallDir
2006
2007    !undef _MOZFUNC_UN
2008    !define _MOZFUNC_UN
2009    !verbose pop
2010  !endif
2011!macroend
2012
2013/**
2014 * Checks whether there is sufficient free space available for the installation
2015 * directory using GetDiskFreeSpaceExW which respects disk quotas. This macro
2016 * will calculate the size of all sections that are selected, compare that with
2017 * the free space available, and if there is sufficient free space it will
2018 * return true... if not, it will return false.
2019 *
2020 * @return  _RESULT
2021 *          "true" if there is sufficient free space otherwise "false".
2022 *
2023 * $R5 = return value from SectionGetSize
2024 * $R6 = return value from SectionGetFlags
2025 *       return value from an 'and' comparison of SectionGetFlags (1=selected)
2026 *       return value for lpFreeBytesAvailable from GetDiskFreeSpaceExW
2027 *       return value for System::Int64Op $R6 / 1024
2028 *       return value for System::Int64Op $R6 > $R8
2029 * $R7 = the counter for enumerating the sections
2030 *       the temporary file name for the directory created under $INSTDIR passed
2031 *       to GetDiskFreeSpaceExW.
2032 * $R8 = sum in KB of all selected sections
2033 * $R9 = _RESULT
2034 */
2035!macro CheckDiskSpace
2036
2037  !ifndef ${_MOZFUNC_UN}CheckDiskSpace
2038    !verbose push
2039    !verbose ${_MOZFUNC_VERBOSE}
2040    !define ${_MOZFUNC_UN}CheckDiskSpace "!insertmacro ${_MOZFUNC_UN}CheckDiskSpaceCall"
2041
2042    Function ${_MOZFUNC_UN}CheckDiskSpace
2043      Push $R9
2044      Push $R8
2045      Push $R7
2046      Push $R6
2047      Push $R5
2048
2049      ClearErrors
2050
2051      StrCpy $R9 "true" ; default return value
2052      StrCpy $R8 "0"    ; sum in KB of all selected sections
2053      StrCpy $R7 "0"    ; counter for enumerating sections
2054
2055      ; Enumerate the sections and sum up the sizes of the sections that are
2056      ; selected.
2057      SectionGetFlags $R7 $R6
2058      IfErrors +7 +1
2059      IntOp $R6 ${SF_SELECTED} & $R6
2060      IntCmp $R6 0 +3 +1 +1
2061      SectionGetSize $R7 $R5
2062      IntOp $R8 $R8 + $R5
2063      IntOp $R7 $R7 + 1
2064      GoTo -7
2065
2066      ; The directory passed to GetDiskFreeSpaceExW must exist for the call to
2067      ; succeed.  Since the CanWriteToInstallDir macro is called prior to this
2068      ; macro the call to CreateDirectory will always succeed.
2069
2070      ; IfFileExists returns false for $INSTDIR when $INSTDIR is the root of a
2071      ; UNC path so always try to create $INSTDIR
2072      CreateDirectory "$INSTDIR\"
2073      GetTempFileName $R7 "$INSTDIR\"
2074      Delete "$R7"
2075      CreateDirectory "$R7"
2076
2077      System::Call 'kernel32::GetDiskFreeSpaceExW(w, *l, *l, *l) i(R7, .R6, ., .) .'
2078
2079      ; Convert to KB for comparison with $R8 which is in KB
2080      System::Int64Op $R6 / 1024
2081      Pop $R6
2082
2083      System::Int64Op $R6 > $R8
2084      Pop $R6
2085
2086      IntCmp $R6 1 end +1 +1
2087      StrCpy $R9 "false"
2088
2089      end:
2090      RmDir "$R7"
2091      RmDir "$INSTDIR\" ; Only remove $INSTDIR if it is empty
2092
2093      ClearErrors
2094
2095      Pop $R5
2096      Pop $R6
2097      Pop $R7
2098      Pop $R8
2099      Exch $R9
2100    FunctionEnd
2101
2102    !verbose pop
2103  !endif
2104!macroend
2105
2106!macro CheckDiskSpaceCall _RESULT
2107  !verbose push
2108  !verbose ${_MOZFUNC_VERBOSE}
2109  Call CheckDiskSpace
2110  Pop ${_RESULT}
2111  !verbose pop
2112!macroend
2113
2114!macro un.CheckDiskSpaceCall _RESULT
2115  !verbose push
2116  !verbose ${_MOZFUNC_VERBOSE}
2117  Call un.CheckDiskSpace
2118  Pop ${_RESULT}
2119  !verbose pop
2120!macroend
2121
2122!macro un.CheckDiskSpace
2123  !ifndef un.CheckDiskSpace
2124    !verbose push
2125    !verbose ${_MOZFUNC_VERBOSE}
2126    !undef _MOZFUNC_UN
2127    !define _MOZFUNC_UN "un."
2128
2129    !insertmacro CheckDiskSpace
2130
2131    !undef _MOZFUNC_UN
2132    !define _MOZFUNC_UN
2133    !verbose pop
2134  !endif
2135!macroend
2136
2137/**
2138* Returns the path found within a passed in string. The path is quoted or not
2139* with the exception of an unquoted non 8dot3 path without arguments that is
2140* also not a DefaultIcon path, is a 8dot3 path or not, has command line
2141* arguments, or is a registry DefaultIcon path (e.g. <path to binary>,# where #
2142* is the icon's resuorce id). The string does not need to be a valid path or
2143* exist. It is up to the caller to pass in a string of one of the forms noted
2144* above and to verify existence if necessary.
2145*
2146* Examples:
2147* In:  C:\PROGRA~1\MOZILL~1\FIREFOX.EXE -flag "%1"
2148* In:  C:\PROGRA~1\MOZILL~1\FIREFOX.EXE,0
2149* In:  C:\PROGRA~1\MOZILL~1\FIREFOX.EXE
2150* In:  "C:\PROGRA~1\MOZILL~1\FIREFOX.EXE"
2151* In:  "C:\PROGRA~1\MOZILL~1\FIREFOX.EXE" -flag "%1"
2152* Out: C:\PROGRA~1\MOZILL~1\FIREFOX.EXE
2153*
2154* In:  "C:\Program Files\Mozilla Firefox\firefox.exe" -flag "%1"
2155* In:  C:\Program Files\Mozilla Firefox\firefox.exe,0
2156* In:  "C:\Program Files\Mozilla Firefox\firefox.exe"
2157* Out: C:\Program Files\Mozilla Firefox\firefox.exe
2158*
2159* @param   _IN_PATH
2160*          The string containing the path.
2161* @param   _OUT_PATH
2162*          The register to store the path to.
2163*
2164* $R7 = counter for the outer loop's EnumRegKey
2165* $R8 = return value from ReadRegStr
2166* $R9 = _IN_PATH and _OUT_PATH
2167*/
2168!macro GetPathFromString
2169
2170  !ifndef ${_MOZFUNC_UN}GetPathFromString
2171    !verbose push
2172    !verbose ${_MOZFUNC_VERBOSE}
2173    !define ${_MOZFUNC_UN}GetPathFromString "!insertmacro ${_MOZFUNC_UN}GetPathFromStringCall"
2174
2175    Function ${_MOZFUNC_UN}GetPathFromString
2176      Exch $R9
2177      Push $R8
2178      Push $R7
2179
2180      StrCpy $R7 0          ; Set the counter to 0.
2181
2182      ; Handle quoted paths with arguments.
2183      StrCpy $R8 $R9 1      ; Copy the first char.
2184      StrCmp $R8 '"' +2 +1  ; Is it a "?
2185      StrCmp $R8 "'" +1 +9  ; Is it a '?
2186      StrCpy $R9 $R9 "" 1   ; Remove the first char.
2187      IntOp $R7 $R7 + 1     ; Increment the counter.
2188      StrCpy $R8 $R9 1 $R7  ; Starting from the counter copy the next char.
2189      StrCmp $R8 "" end +1  ; Are there no more chars?
2190      StrCmp $R8 '"' +2 +1  ; Is it a " char?
2191      StrCmp $R8 "'" +1 -4  ; Is it a ' char?
2192      StrCpy $R9 $R9 $R7    ; Copy chars up to the counter.
2193      GoTo end
2194
2195      ; Handle DefaultIcon paths. DefaultIcon paths are not quoted and end with
2196      ; a , and a number.
2197      IntOp $R7 $R7 - 1     ; Decrement the counter.
2198      StrCpy $R8 $R9 1 $R7  ; Copy one char from the end minus the counter.
2199      StrCmp $R8 '' +4 +1   ; Are there no more chars?
2200      StrCmp $R8 ',' +1 -3  ; Is it a , char?
2201      StrCpy $R9 $R9 $R7    ; Copy chars up to the end minus the counter.
2202      GoTo end
2203
2204      ; Handle unquoted paths with arguments. An unquoted path with arguments
2205      ; must be an 8dot3 path.
2206      StrCpy $R7 -1          ; Set the counter to -1 so it will start at 0.
2207      IntOp $R7 $R7 + 1      ; Increment the counter.
2208      StrCpy $R8 $R9 1 $R7   ; Starting from the counter copy the next char.
2209      StrCmp $R8 "" end +1   ; Are there no more chars?
2210      StrCmp $R8 " " +1 -3   ; Is it a space char?
2211      StrCpy $R9 $R9 $R7     ; Copy chars up to the counter.
2212
2213      end:
2214      ClearErrors
2215
2216      Pop $R7
2217      Pop $R8
2218      Exch $R9
2219    FunctionEnd
2220
2221    !verbose pop
2222  !endif
2223!macroend
2224
2225!macro GetPathFromStringCall _IN_PATH _OUT_PATH
2226  !verbose push
2227  !verbose ${_MOZFUNC_VERBOSE}
2228  Push "${_IN_PATH}"
2229  Call GetPathFromString
2230  Pop ${_OUT_PATH}
2231  !verbose pop
2232!macroend
2233
2234!macro un.GetPathFromStringCall _IN_PATH _OUT_PATH
2235  !verbose push
2236  !verbose ${_MOZFUNC_VERBOSE}
2237  Push "${_IN_PATH}"
2238  Call un.GetPathFromString
2239  Pop ${_OUT_PATH}
2240  !verbose pop
2241!macroend
2242
2243!macro un.GetPathFromString
2244  !ifndef un.GetPathFromString
2245    !verbose push
2246    !verbose ${_MOZFUNC_VERBOSE}
2247    !undef _MOZFUNC_UN
2248    !define _MOZFUNC_UN "un."
2249
2250    !insertmacro GetPathFromString
2251
2252    !undef _MOZFUNC_UN
2253    !define _MOZFUNC_UN
2254    !verbose pop
2255  !endif
2256!macroend
2257
2258/**
2259 * Removes the quotes from each end of a string if present.
2260 *
2261 * @param   _IN_PATH
2262 *          The string containing the path.
2263 * @param   _OUT_PATH
2264 *          The register to store the long path.
2265 *
2266 * $R7 = storage for single character comparison
2267 * $R8 = storage for _IN_PATH
2268 * $R9 = _IN_PATH and _OUT_PATH
2269 */
2270!macro RemoveQuotesFromPath
2271
2272  !ifndef ${_MOZFUNC_UN}RemoveQuotesFromPath
2273    !verbose push
2274    !verbose ${_MOZFUNC_VERBOSE}
2275    !define ${_MOZFUNC_UN}RemoveQuotesFromPath "!insertmacro ${_MOZFUNC_UN}RemoveQuotesFromPathCall"
2276
2277    Function ${_MOZFUNC_UN}RemoveQuotesFromPath
2278      Exch $R9
2279      Push $R8
2280      Push $R7
2281
2282      StrCpy $R7 "$R9" 1
2283      StrCmp $R7 "$\"" +1 +2
2284      StrCpy $R9 "$R9" "" 1
2285
2286      StrCpy $R7 "$R9" "" -1
2287      StrCmp $R7 "$\"" +1 +2
2288      StrCpy $R9 "$R9" -1
2289
2290      Pop $R7
2291      Pop $R8
2292      Exch $R9
2293    FunctionEnd
2294
2295    !verbose pop
2296  !endif
2297!macroend
2298
2299!macro RemoveQuotesFromPathCall _IN_PATH _OUT_PATH
2300  !verbose push
2301  !verbose ${_MOZFUNC_VERBOSE}
2302  Push "${_IN_PATH}"
2303  Call RemoveQuotesFromPath
2304  Pop ${_OUT_PATH}
2305  !verbose pop
2306!macroend
2307
2308!macro un.RemoveQuotesFromPathCall _IN_PATH _OUT_PATH
2309  !verbose push
2310  !verbose ${_MOZFUNC_VERBOSE}
2311  Push "${_IN_PATH}"
2312  Call un.RemoveQuotesFromPath
2313  Pop ${_OUT_PATH}
2314  !verbose pop
2315!macroend
2316
2317!macro un.RemoveQuotesFromPath
2318  !ifndef un.RemoveQuotesFromPath
2319    !verbose push
2320    !verbose ${_MOZFUNC_VERBOSE}
2321    !undef _MOZFUNC_UN
2322    !define _MOZFUNC_UN "un."
2323
2324    !insertmacro RemoveQuotesFromPath
2325
2326    !undef _MOZFUNC_UN
2327    !define _MOZFUNC_UN
2328    !verbose pop
2329  !endif
2330!macroend
2331
2332/**
2333 * Returns the long path for an existing file or directory. GetLongPathNameW
2334 * may not be available on Win95 if Microsoft Layer for Unicode is not
2335 * installed and GetFullPathName only returns a long path for the last file or
2336 * directory that doesn't end with a \ in the path that it is passed. If the
2337 * path does not exist on the file system this will return an empty string. To
2338 * provide a consistent result trailing back-slashes are always removed.
2339 *
2340 * Note: 1024 used by GetLongPathNameW is the maximum NSIS string length.
2341 *
2342 * @param   _IN_PATH
2343 *          The string containing the path.
2344 * @param   _OUT_PATH
2345 *          The register to store the long path.
2346 *
2347 * $R4 = counter value when the previous \ was found
2348 * $R5 = directory or file name found during loop
2349 * $R6 = return value from GetLongPathNameW and loop counter
2350 * $R7 = long path from GetLongPathNameW and single char from path for comparison
2351 * $R8 = storage for _IN_PATH
2352 * $R9 = _IN_PATH _OUT_PATH
2353 */
2354!macro GetLongPath
2355
2356  !ifndef ${_MOZFUNC_UN}GetLongPath
2357    !verbose push
2358    !verbose ${_MOZFUNC_VERBOSE}
2359    !define ${_MOZFUNC_UN}GetLongPath "!insertmacro ${_MOZFUNC_UN}GetLongPathCall"
2360
2361    Function ${_MOZFUNC_UN}GetLongPath
2362      Exch $R9
2363      Push $R8
2364      Push $R7
2365      Push $R6
2366      Push $R5
2367      Push $R4
2368
2369      ClearErrors
2370
2371      GetFullPathName $R8 "$R9"
2372      IfErrors end_GetLongPath +1 ; If the path doesn't exist return an empty string.
2373
2374      System::Call 'kernel32::GetLongPathNameW(w R8, w .R7, i 1024)i .R6'
2375      StrCmp "$R7" "" +4 +1 ; Empty string when GetLongPathNameW is not present.
2376      StrCmp $R6 0 +3 +1    ; Should never equal 0 since the path exists.
2377      StrCpy $R9 "$R7"
2378      GoTo end_GetLongPath
2379
2380      ; Do it the hard way.
2381      StrCpy $R4 0     ; Stores the position in the string of the last \ found.
2382      StrCpy $R6 -1    ; Set the counter to -1 so it will start at 0.
2383
2384      loop_GetLongPath:
2385      IntOp $R6 $R6 + 1      ; Increment the counter.
2386      StrCpy $R7 $R8 1 $R6   ; Starting from the counter copy the next char.
2387      StrCmp $R7 "" +2 +1    ; Are there no more chars?
2388      StrCmp $R7 "\" +1 -3   ; Is it a \?
2389
2390      ; Copy chars starting from the previously found \ to the counter.
2391      StrCpy $R5 $R8 $R6 $R4
2392
2393      ; If this is the first \ found we want to swap R9 with R5 so a \ will
2394      ; be appended to the drive letter and colon (e.g. C: will become C:\).
2395      StrCmp $R4 0 +1 +3
2396      StrCpy $R9 $R5
2397      StrCpy $R5 ""
2398
2399      GetFullPathName $R9 "$R9\$R5"
2400
2401      StrCmp $R7 "" end_GetLongPath +1 ; Are there no more chars?
2402
2403      ; Store the counter for the current \ and prefix it for StrCpy operations.
2404      StrCpy $R4 "+$R6"
2405      IntOp $R6 $R6 + 1      ; Increment the counter so we skip over the \.
2406      StrCpy $R8 $R8 "" $R6  ; Copy chars starting from the counter to the end.
2407      StrCpy $R6 -1          ; Reset the counter to -1 so it will start over at 0.
2408      GoTo loop_GetLongPath
2409
2410      end_GetLongPath:
2411      ; If there is a trailing slash remove it
2412      StrCmp $R9 "" +4 +1
2413      StrCpy $R8 "$R9" "" -1
2414      StrCmp $R8 "\" +1 +2
2415      StrCpy $R9 "$R9" -1
2416
2417      ClearErrors
2418
2419      Pop $R4
2420      Pop $R5
2421      Pop $R6
2422      Pop $R7
2423      Pop $R8
2424      Exch $R9
2425    FunctionEnd
2426
2427    !verbose pop
2428  !endif
2429!macroend
2430
2431!macro GetLongPathCall _IN_PATH _OUT_PATH
2432  !verbose push
2433  !verbose ${_MOZFUNC_VERBOSE}
2434  Push "${_IN_PATH}"
2435  Call GetLongPath
2436  Pop ${_OUT_PATH}
2437  !verbose pop
2438!macroend
2439
2440!macro un.GetLongPathCall _IN_PATH _OUT_PATH
2441  !verbose push
2442  !verbose ${_MOZFUNC_VERBOSE}
2443  Push "${_IN_PATH}"
2444  Call un.GetLongPath
2445  Pop ${_OUT_PATH}
2446  !verbose pop
2447!macroend
2448
2449!macro un.GetLongPath
2450  !ifndef un.GetLongPath
2451    !verbose push
2452    !verbose ${_MOZFUNC_VERBOSE}
2453    !undef _MOZFUNC_UN
2454    !define _MOZFUNC_UN "un."
2455
2456    !insertmacro GetLongPath
2457
2458    !undef _MOZFUNC_UN
2459    !define _MOZFUNC_UN
2460    !verbose pop
2461  !endif
2462!macroend
2463
2464
2465################################################################################
2466# Macros for cleaning up the registry and file system
2467
2468/**
2469 * Removes registry keys that reference this install location and for paths that
2470 * no longer exist. This uses SHCTX to determine the registry hive so you must
2471 * call SetShellVarContext first.
2472 *
2473 * @param   _KEY
2474 *          The registry subkey (typically this will be Software\Mozilla).
2475 *
2476 * XXXrstrong - there is the potential for Key: Software/Mozilla/AppName,
2477 * ValueName: CurrentVersion, ValueData: AppVersion to reference a key that is
2478 * no longer available due to this cleanup. This should be no worse than prior
2479 * to this reg cleanup since the referenced key would be for an app that is no
2480 * longer installed on the system.
2481 *
2482 * $R0 = on x64 systems set to 'false' at the beginning of the macro when
2483 *       enumerating the x86 registry view and set to 'true' when enumerating
2484 *       the x64 registry view.
2485 * $R1 = stores the long path to $INSTDIR
2486 * $R2 = return value from the stack from the GetParent and GetLongPath macros
2487 * $R3 = return value from the outer loop's EnumRegKey
2488 * $R4 = return value from the inner loop's EnumRegKey
2489 * $R5 = return value from ReadRegStr
2490 * $R6 = counter for the outer loop's EnumRegKey
2491 * $R7 = counter for the inner loop's EnumRegKey
2492 * $R8 = return value from the stack from the RemoveQuotesFromPath macro
2493 * $R9 = _KEY
2494 */
2495!macro RegCleanMain
2496
2497  !ifndef ${_MOZFUNC_UN}RegCleanMain
2498    !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN}
2499    !insertmacro ${_MOZFUNC_UN_TMP}GetParent
2500    !insertmacro ${_MOZFUNC_UN_TMP}GetLongPath
2501    !insertmacro ${_MOZFUNC_UN_TMP}RemoveQuotesFromPath
2502    !undef _MOZFUNC_UN
2503    !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP}
2504    !undef _MOZFUNC_UN_TMP
2505
2506    !verbose push
2507    !verbose ${_MOZFUNC_VERBOSE}
2508    !define ${_MOZFUNC_UN}RegCleanMain "!insertmacro ${_MOZFUNC_UN}RegCleanMainCall"
2509
2510    Function ${_MOZFUNC_UN}RegCleanMain
2511      Exch $R9
2512      Push $R8
2513      Push $R7
2514      Push $R6
2515      Push $R5
2516      Push $R4
2517      Push $R3
2518      Push $R2
2519      Push $R1
2520      Push $R0
2521
2522      ${${_MOZFUNC_UN}GetLongPath} "$INSTDIR" $R1
2523      StrCpy $R6 0  ; set the counter for the outer loop to 0
2524
2525      ${If} ${RunningX64}
2526        StrCpy $R0 "false"
2527        ; Set the registry to the 32 bit registry for 64 bit installations or to
2528        ; the 64 bit registry for 32 bit installations at the beginning so it can
2529        ; easily be set back to the correct registry view when finished.
2530        !ifdef HAVE_64BIT_BUILD
2531          SetRegView 32
2532        !else
2533          SetRegView 64
2534        !endif
2535      ${EndIf}
2536
2537      outerloop:
2538      EnumRegKey $R3 SHCTX $R9 $R6
2539      StrCmp $R3 "" end +1  ; if empty there are no more keys to enumerate
2540      IntOp $R6 $R6 + 1     ; increment the outer loop's counter
2541      ClearErrors
2542      ReadRegStr $R5 SHCTX "$R9\$R3\bin" "PathToExe"
2543      IfErrors 0 outercontinue
2544      StrCpy $R7 0  ; set the counter for the inner loop to 0
2545
2546      innerloop:
2547      EnumRegKey $R4 SHCTX "$R9\$R3" $R7
2548      StrCmp $R4 "" outerloop +1  ; if empty there are no more keys to enumerate
2549      IntOp $R7 $R7 + 1  ; increment the inner loop's counter
2550      ClearErrors
2551      ReadRegStr $R5 SHCTX "$R9\$R3\$R4\Main" "PathToExe"
2552      IfErrors innerloop
2553
2554      ${${_MOZFUNC_UN}RemoveQuotesFromPath} "$R5" $R8
2555      ${${_MOZFUNC_UN}GetParent} "$R8" $R2
2556      ${${_MOZFUNC_UN}GetLongPath} "$R2" $R2
2557      IfFileExists "$R2" +1 innerloop
2558      StrCmp "$R2" "$R1" +1 innerloop
2559
2560      ClearErrors
2561      DeleteRegKey SHCTX "$R9\$R3\$R4"
2562      IfErrors innerloop
2563      IntOp $R7 $R7 - 1 ; decrement the inner loop's counter when the key is deleted successfully.
2564      ClearErrors
2565      DeleteRegKey /ifempty SHCTX "$R9\$R3"
2566      IfErrors innerloop outerdecrement
2567
2568      outercontinue:
2569      ${${_MOZFUNC_UN}RemoveQuotesFromPath} "$R5" $R8
2570      ${${_MOZFUNC_UN}GetParent} "$R8" $R2
2571      ${${_MOZFUNC_UN}GetLongPath} "$R2" $R2
2572      IfFileExists "$R2" +1 outerloop
2573      StrCmp "$R2" "$R1" +1 outerloop
2574
2575      ClearErrors
2576      DeleteRegKey SHCTX "$R9\$R3"
2577      IfErrors outerloop
2578
2579      outerdecrement:
2580      IntOp $R6 $R6 - 1 ; decrement the outer loop's counter when the key is deleted successfully.
2581      GoTo outerloop
2582
2583      end:
2584      ${If} ${RunningX64}
2585      ${AndIf} "$R0" == "false"
2586        ; Set the registry to the correct view.
2587        !ifdef HAVE_64BIT_BUILD
2588          SetRegView 64
2589        !else
2590          SetRegView 32
2591        !endif
2592
2593        StrCpy $R6 0  ; set the counter for the outer loop to 0
2594        StrCpy $R0 "true"
2595        GoTo outerloop
2596      ${EndIf}
2597
2598      ClearErrors
2599
2600      Pop $R0
2601      Pop $R1
2602      Pop $R2
2603      Pop $R3
2604      Pop $R4
2605      Pop $R5
2606      Pop $R6
2607      Pop $R7
2608      Pop $R8
2609      Exch $R9
2610    FunctionEnd
2611
2612    !verbose pop
2613  !endif
2614!macroend
2615
2616!macro RegCleanMainCall _KEY
2617  !verbose push
2618  !verbose ${_MOZFUNC_VERBOSE}
2619  Push "${_KEY}"
2620  Call RegCleanMain
2621  !verbose pop
2622!macroend
2623
2624!macro un.RegCleanMainCall _KEY
2625  !verbose push
2626  !verbose ${_MOZFUNC_VERBOSE}
2627  Push "${_KEY}"
2628  Call un.RegCleanMain
2629  !verbose pop
2630!macroend
2631
2632!macro un.RegCleanMain
2633  !ifndef un.RegCleanMain
2634    !verbose push
2635    !verbose ${_MOZFUNC_VERBOSE}
2636    !undef _MOZFUNC_UN
2637    !define _MOZFUNC_UN "un."
2638
2639    !insertmacro RegCleanMain
2640
2641    !undef _MOZFUNC_UN
2642    !define _MOZFUNC_UN
2643    !verbose pop
2644  !endif
2645!macroend
2646
2647/**
2648 * Removes all registry keys from \Software\Windows\CurrentVersion\Uninstall
2649 * that reference this install location in both the 32 bit and 64 bit registry
2650 * view. This macro uses SHCTX to determine the registry hive so you must call
2651 * SetShellVarContext first.
2652 *
2653 * $R3 = on x64 systems set to 'false' at the beginning of the macro when
2654 *       enumerating the x86 registry view and set to 'true' when enumerating
2655 *       the x64 registry view.
2656 * $R4 = stores the long path to $INSTDIR
2657 * $R5 = return value from ReadRegStr
2658 * $R6 = string for the base reg key (e.g. Software\Microsoft\Windows\CurrentVersion\Uninstall)
2659 * $R7 = return value from EnumRegKey
2660 * $R8 = counter for EnumRegKey
2661 * $R9 = return value from the stack from the RemoveQuotesFromPath and GetLongPath macros
2662 */
2663!macro RegCleanUninstall
2664
2665  !ifndef ${_MOZFUNC_UN}RegCleanUninstall
2666    !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN}
2667    !insertmacro ${_MOZFUNC_UN_TMP}GetLongPath
2668    !insertmacro ${_MOZFUNC_UN_TMP}RemoveQuotesFromPath
2669    !undef _MOZFUNC_UN
2670    !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP}
2671    !undef _MOZFUNC_UN_TMP
2672
2673    !verbose push
2674    !verbose ${_MOZFUNC_VERBOSE}
2675    !define ${_MOZFUNC_UN}RegCleanUninstall "!insertmacro ${_MOZFUNC_UN}RegCleanUninstallCall"
2676
2677    Function ${_MOZFUNC_UN}RegCleanUninstall
2678      Push $R9
2679      Push $R8
2680      Push $R7
2681      Push $R6
2682      Push $R5
2683      Push $R4
2684      Push $R3
2685
2686      ${${_MOZFUNC_UN}GetLongPath} "$INSTDIR" $R4
2687      StrCpy $R6 "Software\Microsoft\Windows\CurrentVersion\Uninstall"
2688      StrCpy $R7 ""
2689      StrCpy $R8 0
2690
2691      ${If} ${RunningX64}
2692        StrCpy $R3 "false"
2693        ; Set the registry to the 32 bit registry for 64 bit installations or to
2694        ; the 64 bit registry for 32 bit installations at the beginning so it can
2695        ; easily be set back to the correct registry view when finished.
2696        !ifdef HAVE_64BIT_BUILD
2697          SetRegView 32
2698        !else
2699          SetRegView 64
2700        !endif
2701      ${EndIf}
2702
2703      loop:
2704      EnumRegKey $R7 SHCTX $R6 $R8
2705      StrCmp $R7 "" end +1
2706      IntOp $R8 $R8 + 1 ; Increment the counter
2707      ClearErrors
2708      ReadRegStr $R5 SHCTX "$R6\$R7" "InstallLocation"
2709      IfErrors loop
2710      ${${_MOZFUNC_UN}RemoveQuotesFromPath} "$R5" $R9
2711
2712      ; Detect when the path is just a drive letter without a trailing
2713      ; backslash (e.g., "C:"), and add a backslash. If we don't, the Win32
2714      ; calls in GetLongPath will interpret that syntax as a shorthand
2715      ; for the working directory, because that's the DOS 2.0 convention,
2716      ; and will return the path to that directory instead of just the drive.
2717      ; Back here, we would then successfully match that with our $INSTDIR,
2718      ; and end up deleting a registry key that isn't really ours.
2719      StrLen $R5 "$R9"
2720      ${If} $R5 == 2
2721        StrCpy $R5 "$R9" 1 1
2722        ${If} "$R5" == ":"
2723          StrCpy $R9 "$R9\"
2724        ${EndIf}
2725      ${EndIf}
2726
2727      ${${_MOZFUNC_UN}GetLongPath} "$R9" $R9
2728      StrCmp "$R9" "$R4" +1 loop
2729      ClearErrors
2730      DeleteRegKey SHCTX "$R6\$R7"
2731      IfErrors loop +1
2732      IntOp $R8 $R8 - 1 ; Decrement the counter on successful deletion
2733      GoTo loop
2734
2735      end:
2736      ${If} ${RunningX64}
2737      ${AndIf} "$R3" == "false"
2738        ; Set the registry to the correct view.
2739        !ifdef HAVE_64BIT_BUILD
2740          SetRegView 64
2741        !else
2742          SetRegView 32
2743        !endif
2744
2745        StrCpy $R7 ""
2746        StrCpy $R8 0
2747        StrCpy $R3 "true"
2748        GoTo loop
2749      ${EndIf}
2750
2751      ClearErrors
2752
2753      Pop $R3
2754      Pop $R4
2755      Pop $R5
2756      Pop $R6
2757      Pop $R7
2758      Pop $R8
2759      Pop $R9
2760    FunctionEnd
2761
2762    !verbose pop
2763  !endif
2764!macroend
2765
2766!macro RegCleanUninstallCall
2767  !verbose push
2768  !verbose ${_MOZFUNC_VERBOSE}
2769  Call RegCleanUninstall
2770  !verbose pop
2771!macroend
2772
2773!macro un.RegCleanUninstallCall
2774  !verbose push
2775  !verbose ${_MOZFUNC_VERBOSE}
2776  Call un.RegCleanUninstall
2777  !verbose pop
2778!macroend
2779
2780!macro un.RegCleanUninstall
2781  !ifndef un.RegCleanUninstall
2782    !verbose push
2783    !verbose ${_MOZFUNC_VERBOSE}
2784    !undef _MOZFUNC_UN
2785    !define _MOZFUNC_UN "un."
2786
2787    !insertmacro RegCleanUninstall
2788
2789    !undef _MOZFUNC_UN
2790    !define _MOZFUNC_UN
2791    !verbose pop
2792  !endif
2793!macroend
2794
2795/**
2796 * Removes an application specific handler registry key under Software\Classes
2797 * for both HKCU and HKLM when its open command refers to this install
2798 * location or the install location doesn't exist.
2799 *
2800 * @param   _HANDLER_NAME
2801 *          The registry name for the handler.
2802 *
2803 * $R7 = stores the long path to the $INSTDIR
2804 * $R8 = stores the path to the open command's parent directory
2805 * $R9 = _HANDLER_NAME
2806 */
2807!macro RegCleanAppHandler
2808
2809  !ifndef ${_MOZFUNC_UN}RegCleanAppHandler
2810    !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN}
2811    !insertmacro ${_MOZFUNC_UN_TMP}GetLongPath
2812    !insertmacro ${_MOZFUNC_UN_TMP}GetParent
2813    !insertmacro ${_MOZFUNC_UN_TMP}GetPathFromString
2814    !undef _MOZFUNC_UN
2815    !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP}
2816    !undef _MOZFUNC_UN_TMP
2817
2818    !verbose push
2819    !verbose ${_MOZFUNC_VERBOSE}
2820    !define ${_MOZFUNC_UN}RegCleanAppHandler "!insertmacro ${_MOZFUNC_UN}RegCleanAppHandlerCall"
2821
2822    Function ${_MOZFUNC_UN}RegCleanAppHandler
2823      Exch $R9
2824      Push $R8
2825      Push $R7
2826
2827      ClearErrors
2828      ReadRegStr $R8 HKCU "Software\Classes\$R9\shell\open\command" ""
2829      IfErrors next +1
2830      ${${_MOZFUNC_UN}GetPathFromString} "$R8" $R8
2831      ${${_MOZFUNC_UN}GetParent} "$R8" $R8
2832      IfFileExists "$R8" +3 +1
2833      DeleteRegKey HKCU "Software\Classes\$R9"
2834      GoTo next
2835
2836      ${${_MOZFUNC_UN}GetLongPath} "$R8" $R8
2837      ${${_MOZFUNC_UN}GetLongPath} "$INSTDIR" $R7
2838      StrCmp "$R7" "$R8" +1 next
2839      DeleteRegKey HKCU "Software\Classes\$R9"
2840
2841      next:
2842      ReadRegStr $R8 HKLM "Software\Classes\$R9\shell\open\command" ""
2843      IfErrors end
2844      ${${_MOZFUNC_UN}GetPathFromString} "$R8" $R8
2845      ${${_MOZFUNC_UN}GetParent} "$R8" $R8
2846      IfFileExists "$R8" +3 +1
2847      DeleteRegKey HKLM "Software\Classes\$R9"
2848      GoTo end
2849
2850      ${${_MOZFUNC_UN}GetLongPath} "$R8" $R8
2851      ${${_MOZFUNC_UN}GetLongPath} "$INSTDIR" $R7
2852      StrCmp "$R7" "$R8" +1 end
2853      DeleteRegKey HKLM "Software\Classes\$R9"
2854
2855      end:
2856
2857      Pop $R7
2858      Pop $R8
2859      Exch $R9
2860    FunctionEnd
2861
2862    !verbose pop
2863  !endif
2864!macroend
2865
2866!macro RegCleanAppHandlerCall _HANDLER_NAME
2867  !verbose push
2868  !verbose ${_MOZFUNC_VERBOSE}
2869  Push "${_HANDLER_NAME}"
2870  Call RegCleanAppHandler
2871  !verbose pop
2872!macroend
2873
2874!macro un.RegCleanAppHandlerCall _HANDLER_NAME
2875  !verbose push
2876  !verbose ${_MOZFUNC_VERBOSE}
2877  Push "${_HANDLER_NAME}"
2878  Call un.RegCleanAppHandler
2879  !verbose pop
2880!macroend
2881
2882!macro un.RegCleanAppHandler
2883  !ifndef un.RegCleanAppHandler
2884    !verbose push
2885    !verbose ${_MOZFUNC_VERBOSE}
2886    !undef _MOZFUNC_UN
2887    !define _MOZFUNC_UN "un."
2888
2889    !insertmacro RegCleanAppHandler
2890
2891    !undef _MOZFUNC_UN
2892    !define _MOZFUNC_UN
2893    !verbose pop
2894  !endif
2895!macroend
2896
2897/**
2898 * Cleans up the registry for a protocol handler when its open command
2899 * refers to this install location. For HKCU the registry key is deleted
2900 * and for HKLM the values set by the application are deleted.
2901 *
2902 * @param   _HANDLER_NAME
2903 *          The registry name for the handler.
2904 *
2905 * $R7 = stores the long path to $INSTDIR
2906 * $R8 = stores the the long path to the open command's parent directory
2907 * $R9 = _HANDLER_NAME
2908 */
2909!macro un.RegCleanProtocolHandler
2910
2911  !ifndef un.RegCleanProtocolHandler
2912    !insertmacro un.GetLongPath
2913    !insertmacro un.GetParent
2914    !insertmacro un.GetPathFromString
2915
2916    !verbose push
2917    !verbose ${_MOZFUNC_VERBOSE}
2918    !define un.RegCleanProtocolHandler "!insertmacro un.RegCleanProtocolHandlerCall"
2919
2920    Function un.RegCleanProtocolHandler
2921      Exch $R9
2922      Push $R8
2923      Push $R7
2924
2925      ReadRegStr $R8 HKCU "Software\Classes\$R9\shell\open\command" ""
2926      ${un.GetLongPath} "$INSTDIR" $R7
2927
2928      StrCmp "$R8" "" next +1
2929      ${un.GetPathFromString} "$R8" $R8
2930      ${un.GetParent} "$R8" $R8
2931      ${un.GetLongPath} "$R8" $R8
2932      StrCmp "$R7" "$R8" +1 next
2933      DeleteRegKey HKCU "Software\Classes\$R9"
2934
2935      next:
2936      ReadRegStr $R8 HKLM "Software\Classes\$R9\shell\open\command" ""
2937      StrCmp "$R8" "" end +1
2938      ${un.GetLongPath} "$INSTDIR" $R7
2939      ${un.GetPathFromString} "$R8" $R8
2940      ${un.GetParent} "$R8" $R8
2941      ${un.GetLongPath} "$R8" $R8
2942      StrCmp "$R7" "$R8" +1 end
2943      DeleteRegValue HKLM "Software\Classes\$R9\DefaultIcon" ""
2944      DeleteRegValue HKLM "Software\Classes\$R9\shell\open" ""
2945      DeleteRegValue HKLM "Software\Classes\$R9\shell\open\command" ""
2946      DeleteRegValue HKLM "Software\Classes\$R9\shell\ddeexec" ""
2947      DeleteRegValue HKLM "Software\Classes\$R9\shell\ddeexec\Application" ""
2948      DeleteRegValue HKLM "Software\Classes\$R9\shell\ddeexec\Topic" ""
2949
2950      end:
2951
2952      Pop $R7
2953      Pop $R8
2954      Exch $R9
2955    FunctionEnd
2956
2957    !verbose pop
2958  !endif
2959!macroend
2960
2961!macro un.RegCleanProtocolHandlerCall _HANDLER_NAME
2962  !verbose push
2963  !verbose ${_MOZFUNC_VERBOSE}
2964  Push "${_HANDLER_NAME}"
2965  Call un.RegCleanProtocolHandler
2966  !verbose pop
2967!macroend
2968
2969/**
2970 * Cleans up the registry for a file handler when the passed in value equals
2971 * the default value for the file handler. For HKCU the registry key is deleted
2972 * and for HKLM the default value is deleted.
2973 *
2974 * @param   _HANDLER_NAME
2975 *          The registry name for the handler.
2976 * @param   _DEFAULT_VALUE
2977 *          The value to check for against the handler's default value.
2978 *
2979 * $R6 = stores the long path to $INSTDIR
2980 * $R7 = _DEFAULT_VALUE
2981 * $R9 = _HANDLER_NAME
2982 */
2983!macro RegCleanFileHandler
2984
2985  !ifndef ${_MOZFUNC_UN}RegCleanFileHandler
2986    !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN}
2987    !insertmacro ${_MOZFUNC_UN_TMP}GetLongPath
2988    !insertmacro ${_MOZFUNC_UN_TMP}GetParent
2989    !insertmacro ${_MOZFUNC_UN_TMP}GetPathFromString
2990    !undef _MOZFUNC_UN
2991    !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP}
2992    !undef _MOZFUNC_UN_TMP
2993
2994    !verbose push
2995    !verbose ${_MOZFUNC_VERBOSE}
2996    !define ${_MOZFUNC_UN}RegCleanFileHandler "!insertmacro ${_MOZFUNC_UN}RegCleanFileHandlerCall"
2997
2998    Function ${_MOZFUNC_UN}RegCleanFileHandler
2999      Exch $R9
3000      Exch 1
3001      Exch $R8
3002      Push $R7
3003
3004      DeleteRegValue HKCU "Software\Classes\$R9\OpenWithProgids" $R8
3005      EnumRegValue $R7 HKCU "Software\Classes\$R9\OpenWithProgids" 0
3006      StrCmp "$R7" "" +1 +2
3007      DeleteRegKey HKCU "Software\Classes\$R9\OpenWithProgids"
3008      ReadRegStr $R7 HKCU "Software\Classes\$R9" ""
3009      StrCmp "$R7" "$R8" +1 +2
3010      DeleteRegKey HKCU "Software\Classes\$R9"
3011
3012      DeleteRegValue HKLM "Software\Classes\$R9\OpenWithProgids" $R8
3013      EnumRegValue $R7 HKLM "Software\Classes\$R9\OpenWithProgids" 0
3014      StrCmp "$R7" "" +1 +2
3015      DeleteRegKey HKLM "Software\Classes\$R9\OpenWithProgids"
3016      ReadRegStr $R7 HKLM "Software\Classes\$R9" ""
3017      StrCmp "$R7" "$R8" +1 +2
3018      DeleteRegValue HKLM "Software\Classes\$R9" ""
3019
3020      ClearErrors
3021
3022      Pop $R7
3023      Exch $R8
3024      Exch 1
3025      Exch $R9
3026    FunctionEnd
3027
3028    !verbose pop
3029  !endif
3030!macroend
3031
3032!macro RegCleanFileHandlerCall _HANDLER_NAME _DEFAULT_VALUE
3033  !verbose push
3034  !verbose ${_MOZFUNC_VERBOSE}
3035  Push "${_DEFAULT_VALUE}"
3036  Push "${_HANDLER_NAME}"
3037  Call RegCleanFileHandler
3038  !verbose pop
3039!macroend
3040
3041!macro un.RegCleanFileHandlerCall _HANDLER_NAME _DEFAULT_VALUE
3042  !verbose push
3043  !verbose ${_MOZFUNC_VERBOSE}
3044  Push "${_DEFAULT_VALUE}"
3045  Push "${_HANDLER_NAME}"
3046  Call un.RegCleanFileHandler
3047  !verbose pop
3048!macroend
3049
3050!macro un.RegCleanFileHandler
3051  !ifndef un.RegCleanFileHandler
3052    !verbose push
3053    !verbose ${_MOZFUNC_VERBOSE}
3054    !undef _MOZFUNC_UN
3055    !define _MOZFUNC_UN "un."
3056
3057    !insertmacro RegCleanFileHandler
3058
3059    !undef _MOZFUNC_UN
3060    !define _MOZFUNC_UN
3061    !verbose pop
3062  !endif
3063!macroend
3064
3065/**
3066 * Checks if a handler's open command points to this installation directory.
3067 * Uses SHCTX to determine the registry hive (e.g. HKLM or HKCU) to check.
3068 *
3069 * @param   _HANDLER_NAME
3070 *          The registry name for the handler.
3071 * @param   _RESULT
3072 *          true if it is the handler's open command points to this
3073 *          installation directory and false if it does not.
3074 *
3075 * $R7 = stores the value of the open command and the path macros return values
3076 * $R8 = stores the handler's registry key name
3077 * $R9 = _DEFAULT_VALUE and _RESULT
3078 */
3079!macro IsHandlerForInstallDir
3080
3081  !ifndef ${_MOZFUNC_UN}IsHandlerForInstallDir
3082    !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN}
3083    !insertmacro ${_MOZFUNC_UN_TMP}GetLongPath
3084    !insertmacro ${_MOZFUNC_UN_TMP}GetParent
3085    !insertmacro ${_MOZFUNC_UN_TMP}GetPathFromString
3086    !undef _MOZFUNC_UN
3087    !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP}
3088    !undef _MOZFUNC_UN_TMP
3089
3090    !verbose push
3091    !verbose ${_MOZFUNC_VERBOSE}
3092    !define ${_MOZFUNC_UN}IsHandlerForInstallDir "!insertmacro ${_MOZFUNC_UN}IsHandlerForInstallDirCall"
3093
3094    Function ${_MOZFUNC_UN}IsHandlerForInstallDir
3095      Exch $R9
3096      Push $R8
3097      Push $R7
3098
3099      StrCpy $R8 "$R9"
3100      StrCpy $R9 "false"
3101      ReadRegStr $R7 SHCTX "Software\Classes\$R8\shell\open\command" ""
3102
3103      ${If} $R7 != ""
3104        ${GetPathFromString} "$R7" $R7
3105        ${GetParent} "$R7" $R7
3106        ${GetLongPath} "$R7" $R7
3107        ${If} $R7 == $INSTDIR
3108          StrCpy $R9 "true"
3109        ${EndIf}
3110      ${EndIf}
3111
3112      ClearErrors
3113
3114      Pop $R7
3115      Pop $R8
3116      Exch $R9
3117    FunctionEnd
3118
3119    !verbose pop
3120  !endif
3121!macroend
3122
3123!macro IsHandlerForInstallDirCall _HANDLER_NAME _RESULT
3124  !verbose push
3125  !verbose ${_MOZFUNC_VERBOSE}
3126  Push "${_HANDLER_NAME}"
3127  Call IsHandlerForInstallDir
3128  Pop "${_RESULT}"
3129  !verbose pop
3130!macroend
3131
3132!macro un.IsHandlerForInstallDirCall _HANDLER_NAME _RESULT
3133  !verbose push
3134  !verbose ${_MOZFUNC_VERBOSE}
3135  Push "${_HANDLER_NAME}"
3136  Call un.IsHandlerForInstallDir
3137  Pop "${_RESULT}"
3138  !verbose pop
3139!macroend
3140
3141!macro un.IsHandlerForInstallDir
3142  !ifndef un.IsHandlerForInstallDir
3143    !verbose push
3144    !verbose ${_MOZFUNC_VERBOSE}
3145    !undef _MOZFUNC_UN
3146    !define _MOZFUNC_UN "un."
3147
3148    !insertmacro IsHandlerForInstallDir
3149
3150    !undef _MOZFUNC_UN
3151    !define _MOZFUNC_UN
3152    !verbose pop
3153  !endif
3154!macroend
3155
3156/**
3157 * Removes the application's VirtualStore directory if present when the
3158 * installation directory is a sub-directory of the program files directory.
3159 *
3160 * $R4 = $PROGRAMFILES/$PROGRAMFILES64 for CleanVirtualStore_Internal
3161 * $R5 = various path values.
3162 * $R6 = length of the long path to $PROGRAMFILES32 or $PROGRAMFILES64
3163 * $R7 = long path to $PROGRAMFILES32 or $PROGRAMFILES64
3164 * $R8 = length of the long path to $INSTDIR
3165 * $R9 = long path to $INSTDIR
3166 */
3167!macro CleanVirtualStore
3168
3169  !ifndef ${_MOZFUNC_UN}CleanVirtualStore
3170    !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN}
3171    !insertmacro ${_MOZFUNC_UN_TMP}GetLongPath
3172    !undef _MOZFUNC_UN
3173    !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP}
3174    !undef _MOZFUNC_UN_TMP
3175
3176    !verbose push
3177    !verbose ${_MOZFUNC_VERBOSE}
3178    !define ${_MOZFUNC_UN}CleanVirtualStore "!insertmacro ${_MOZFUNC_UN}CleanVirtualStoreCall"
3179
3180    Function ${_MOZFUNC_UN}CleanVirtualStore
3181      Push $R9
3182      Push $R8
3183      Push $R7
3184      Push $R6
3185      Push $R5
3186      Push $R4
3187
3188      ${${_MOZFUNC_UN}GetLongPath} "$INSTDIR" $R9
3189      ${If} "$R9" != ""
3190        StrLen $R8 "$R9"
3191
3192        StrCpy $R4 $PROGRAMFILES32
3193        Call ${_MOZFUNC_UN}CleanVirtualStore_Internal
3194
3195        ${If} ${RunningX64}
3196          StrCpy $R4 $PROGRAMFILES64
3197          Call ${_MOZFUNC_UN}CleanVirtualStore_Internal
3198        ${EndIf}
3199
3200      ${EndIf}
3201
3202      ClearErrors
3203
3204      Pop $R4
3205      Pop $R5
3206      Pop $R6
3207      Pop $R7
3208      Pop $R8
3209      Pop $R9
3210    FunctionEnd
3211
3212    Function ${_MOZFUNC_UN}CleanVirtualStore_Internal
3213      ${${_MOZFUNC_UN}GetLongPath} "" $R7
3214      ${If} "$R7" != ""
3215        StrLen $R6 "$R7"
3216        ${If} $R8 < $R6
3217          ; Copy from the start of $INSTDIR the length of $PROGRAMFILES64
3218          StrCpy $R5 "$R9" $R6
3219          ${If} "$R5" == "$R7"
3220            ; Remove the drive letter and colon from the $INSTDIR long path
3221            StrCpy $R5 "$R9" "" 2
3222            StrCpy $R5 "$LOCALAPPDATA\VirtualStore$R5"
3223            ${${_MOZFUNC_UN}GetLongPath} "$R5" $R5
3224            ${If} "$R5" != ""
3225            ${AndIf} ${FileExists} "$R5"
3226              RmDir /r "$R5"
3227            ${EndIf}
3228          ${EndIf}
3229        ${EndIf}
3230      ${EndIf}
3231    FunctionEnd
3232
3233    !verbose pop
3234  !endif
3235!macroend
3236
3237!macro CleanVirtualStoreCall
3238  !verbose push
3239  !verbose ${_MOZFUNC_VERBOSE}
3240  Call CleanVirtualStore
3241  !verbose pop
3242!macroend
3243
3244!macro un.CleanVirtualStoreCall
3245  !verbose push
3246  !verbose ${_MOZFUNC_VERBOSE}
3247  Call un.CleanVirtualStore
3248  !verbose pop
3249!macroend
3250
3251!macro un.CleanVirtualStore
3252  !ifndef un.CleanVirtualStore
3253    !verbose push
3254    !verbose ${_MOZFUNC_VERBOSE}
3255    !undef _MOZFUNC_UN
3256    !define _MOZFUNC_UN "un."
3257
3258    !insertmacro CleanVirtualStore
3259
3260    !undef _MOZFUNC_UN
3261    !define _MOZFUNC_UN
3262    !verbose pop
3263  !endif
3264!macroend
3265
3266/**
3267 * If present removes the updates directory located in the profile's local
3268 * directory for this installation.
3269 * This macro is obsolete and should no longer be used. Please see
3270 * CleanUpdateDirectories.
3271 *
3272 * @param   _REL_PROFILE_PATH
3273 *          The relative path to the profile directory from $LOCALAPPDATA.
3274 *
3275 * $R4 = various path values.
3276 * $R5 = length of the long path to $PROGRAMFILES
3277 * $R6 = length of the long path to $INSTDIR
3278 * $R7 = long path to $PROGRAMFILES
3279 * $R8 = long path to $INSTDIR
3280 * $R9 = _REL_PROFILE_PATH
3281 */
3282!macro CleanUpdatesDir
3283
3284  !ifndef ${_MOZFUNC_UN}CleanUpdatesDir
3285    !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN}
3286    !insertmacro ${_MOZFUNC_UN_TMP}GetLongPath
3287    !undef _MOZFUNC_UN
3288    !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP}
3289    !undef _MOZFUNC_UN_TMP
3290
3291    !verbose push
3292    !verbose ${_MOZFUNC_VERBOSE}
3293    !define ${_MOZFUNC_UN}CleanUpdatesDir "!insertmacro ${_MOZFUNC_UN}CleanUpdatesDirCall"
3294
3295    Function ${_MOZFUNC_UN}CleanUpdatesDir
3296      Exch $R9
3297      Push $R8
3298      Push $R7
3299      Push $R6
3300      Push $R5
3301      Push $R4
3302
3303      StrCmp $R9 "" end +1 ; The relative path to the app's profiles is required
3304      ${${_MOZFUNC_UN}GetLongPath} "$INSTDIR" $R8
3305      StrCmp $R8 "" end +1
3306      ${${_MOZFUNC_UN}GetLongPath} "$PROGRAMFILES" $R7
3307      StrCmp $R7 "" end +1
3308
3309      StrLen $R6 "$R8"
3310      StrLen $R5 "$R7"
3311      ; Only continue If the length of $INSTDIR is greater than the length of
3312      ; $PROGRAMFILES
3313      IntCmp $R6 $R5 end end +1
3314
3315      ; Copy from the start of $INSTDIR the length of $PROGRAMFILES
3316      StrCpy $R4 "$R8" $R5
3317      StrCmp "$R4" "$R7" +1 end ; Check if $INSTDIR is under $PROGRAMFILES
3318
3319      ; Copy the relative path to $INSTDIR from $PROGRAMFILES
3320      StrCpy $R4 "$R8" "" $R5
3321
3322      ; Concatenate the path to $LOCALAPPDATA the relative profile path and the
3323      ; relative path to $INSTDIR from $PROGRAMFILES
3324      StrCpy $R4 "$LOCALAPPDATA\$R9$R4"
3325      ${${_MOZFUNC_UN}GetLongPath} "$R4" $R4
3326      StrCmp $R4 "" end +1
3327
3328      IfFileExists "$R4\updates" +1 end
3329      RmDir /r "$R4"
3330
3331      end:
3332      ClearErrors
3333
3334      Pop $R4
3335      Pop $R5
3336      Pop $R6
3337      Pop $R7
3338      Pop $R8
3339      Exch $R9
3340    FunctionEnd
3341
3342    !verbose pop
3343  !endif
3344!macroend
3345
3346!macro CleanUpdatesDirCall _REL_PROFILE_PATH
3347  !verbose push
3348  !verbose ${_MOZFUNC_VERBOSE}
3349  Push "${_REL_PROFILE_PATH}"
3350  Call CleanUpdatesDir
3351  !verbose pop
3352!macroend
3353
3354!macro un.CleanUpdatesDirCall _REL_PROFILE_PATH
3355  !verbose push
3356  !verbose ${_MOZFUNC_VERBOSE}
3357  Push "${_REL_PROFILE_PATH}"
3358  Call un.CleanUpdatesDir
3359  !verbose pop
3360!macroend
3361
3362!macro un.CleanUpdatesDir
3363  !ifndef un.CleanUpdatesDir
3364    !verbose push
3365    !verbose ${_MOZFUNC_VERBOSE}
3366    !undef _MOZFUNC_UN
3367    !define _MOZFUNC_UN "un."
3368
3369    !insertmacro CleanUpdatesDir
3370
3371    !undef _MOZFUNC_UN
3372    !define _MOZFUNC_UN
3373    !verbose pop
3374  !endif
3375!macroend
3376
3377/**
3378 * If present removes the updates directory located in the profile's local
3379 * directory for this installation.
3380 *
3381 * @param   _OLD_REL_PATH
3382 *          The relative path to the profile directory from $LOCALAPPDATA.
3383 *          Calculated for the old update directory not based on a hash.
3384 * @param   _NEW_REL_PATH
3385 *          The relative path to the profile directory from $LOCALAPPDATA.
3386 *          Calculated for the new update directory based on a hash.
3387 *
3388 * $R8 = _NEW_REL_PATH
3389 * $R7 = _OLD_REL_PATH
3390 * $R1 = taskBar ID hash located in registry at SOFTWARE\_OLD_REL_PATH\TaskBarIDs
3391 * $R2 = various path values.
3392 * $R3 = length of the long path to $PROGRAMFILES
3393 * $R4 = length of the long path to $INSTDIR
3394 * $R5 = long path to $PROGRAMFILES
3395 * $R6 = long path to $INSTDIR
3396 * $R0 = path to the new update directory built from _NEW_REL_PATH and
3397 *       the taskbar ID.
3398 */
3399!macro CleanUpdateDirectories
3400
3401  !ifndef ${_MOZFUNC_UN}CleanUpdateDirectories
3402    !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN}
3403    !insertmacro ${_MOZFUNC_UN_TMP}GetLongPath
3404    !undef _MOZFUNC_UN
3405    !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP}
3406    !undef _MOZFUNC_UN_TMP
3407
3408    !verbose push
3409    !verbose ${_MOZFUNC_VERBOSE}
3410    !define ${_MOZFUNC_UN}CleanUpdateDirectories "!insertmacro ${_MOZFUNC_UN}CleanUpdateDirectoriesCall"
3411
3412    Function ${_MOZFUNC_UN}CleanUpdateDirectories
3413      Exch $R8
3414      Exch 1
3415      Exch $R7
3416      Push $R6
3417      Push $R5
3418      Push $R4
3419      Push $R3
3420      Push $R2
3421      Push $R1
3422      Push $R0
3423
3424      ${${_MOZFUNC_UN}GetLongPath} "$INSTDIR" $R6
3425      StrLen $R4 "$R6"
3426
3427      ${${_MOZFUNC_UN}GetLongPath} "$PROGRAMFILES" $R5
3428      StrLen $R3 "$R5"
3429
3430      ${If} $R7 != "" ; _OLD_REL_PATH was passed
3431      ${AndIf} $R6 != "" ; We have the install dir path
3432      ${AndIf} $R5 != "" ; We the program files path
3433      ${AndIf} $R4 > $R3 ; The length of $INSTDIR > the length of $PROGRAMFILES
3434
3435        ; Copy from the start of $INSTDIR the length of $PROGRAMFILES
3436        StrCpy $R2 "$R6" $R3
3437
3438        ; Check if $INSTDIR is under $PROGRAMFILES
3439        ${If} $R2 == $R5
3440
3441          ; Copy the relative path to $INSTDIR from $PROGRAMFILES
3442          StrCpy $R2 "$R6" "" $R3
3443
3444          ; Concatenate the path $LOCALAPPDATA to the relative profile path and
3445          ; the relative path to $INSTDIR from $PROGRAMFILES
3446          StrCpy $R2 "$LOCALAPPDATA\$R7$R2"
3447          ${${_MOZFUNC_UN}GetLongPath} "$R2" $R2
3448
3449          ${If} $R2 != ""
3450            ; Backup the old update directory logs and delete the directory
3451            ${If} ${FileExists} "$R2\updates\last-update.log"
3452              Rename "$R2\updates\last-update.log" "$TEMP\moz-update-old-last-update.log"
3453            ${EndIf}
3454
3455            ${If} ${FileExists} "$R2\updates\backup-update.log"
3456              Rename "$R2\updates\backup-update.log" "$TEMP\moz-update-old-backup-update.log"
3457            ${EndIf}
3458
3459            ${If} ${FileExists} "$R2\updates"
3460                RmDir /r "$R2"
3461            ${EndIf}
3462          ${EndIf}
3463
3464          ; Get the taskbar ID hash for this installation path
3465          ReadRegStr $R1 HKLM "SOFTWARE\$R7\TaskBarIDs" $R6
3466          ${If} $R1 == ""
3467            ReadRegStr $R1 HKCU "SOFTWARE\$R7\TaskBarIDs" $R6
3468          ${EndIf}
3469
3470          ; If the taskbar ID hash exists then delete the new update directory
3471          ; Backup its logs before deleting it.
3472          ${If} $R1 != ""
3473            StrCpy $R0 "$LOCALAPPDATA\$R8\$R1"
3474
3475            ${If} ${FileExists} "$R0\updates\last-update.log"
3476              Rename "$R0\updates\last-update.log" "$TEMP\moz-update-new-last-update.log"
3477            ${EndIf}
3478
3479            ${If} ${FileExists} "$R0\updates\backup-update.log"
3480              Rename "$R0\updates\backup-update.log" "$TEMP\moz-update-new-backup-update.log"
3481            ${EndIf}
3482
3483            ; Remove the old updates directory
3484            ${If} ${FileExists} "$R0\updates"
3485              RmDir /r "$R0"
3486            ${EndIf}
3487          ${EndIf}
3488        ${EndIf}
3489      ${EndIf}
3490
3491      ClearErrors
3492
3493      Pop $R0
3494      Pop $R1
3495      Pop $R2
3496      Pop $R3
3497      Pop $R4
3498      Pop $R5
3499      Pop $R6
3500      Exch $R7
3501      Exch 1
3502      Exch $R8
3503    FunctionEnd
3504
3505    !verbose pop
3506  !endif
3507!macroend
3508
3509!macro CleanUpdateDirectoriesCall _OLD_REL_PATH _NEW_REL_PATH
3510  !verbose push
3511  !verbose ${_MOZFUNC_VERBOSE}
3512  Push "${_OLD_REL_PATH}"
3513  Push "${_NEW_REL_PATH}"
3514  Call CleanUpdateDirectories
3515  !verbose pop
3516!macroend
3517
3518!macro un.CleanUpdateDirectoriesCall _OLD_REL_PATH _NEW_REL_PATH
3519  !verbose push
3520  !verbose ${_MOZFUNC_VERBOSE}
3521  Push "${_OLD_REL_PATH}"
3522  Push "${_NEW_REL_PATH}"
3523  Call un.CleanUpdateDirectories
3524  !verbose pop
3525!macroend
3526
3527!macro un.CleanUpdateDirectories
3528  !ifndef un.CleanUpdateDirectories
3529    !verbose push
3530    !verbose ${_MOZFUNC_VERBOSE}
3531    !undef _MOZFUNC_UN
3532    !define _MOZFUNC_UN "un."
3533
3534    !insertmacro CleanUpdateDirectories
3535
3536    !undef _MOZFUNC_UN
3537    !define _MOZFUNC_UN
3538    !verbose pop
3539  !endif
3540!macroend
3541
3542/**
3543 * Deletes all relative profiles specified in an application's profiles.ini and
3544 * performs various other cleanup.
3545 *
3546 * @param   _REL_PROFILE_PATH
3547 *          The relative path to the profile directory.
3548 *
3549 * $R6 = value of IsRelative read from profiles.ini
3550 * $R7 = value of Path to profile read from profiles.ini
3551 * $R8 = counter for reading profiles (e.g. Profile0, Profile1, etc.)
3552 * $R9 = _REL_PROFILE_PATH
3553 */
3554!macro DeleteRelativeProfiles
3555
3556  !ifndef ${_MOZFUNC_UN}DeleteRelativeProfiles
3557    !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN}
3558    !insertmacro ${_MOZFUNC_UN_TMP}WordReplace
3559    !undef _MOZFUNC_UN
3560    !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP}
3561    !undef _MOZFUNC_UN_TMP
3562
3563    !verbose push
3564    !verbose ${_MOZFUNC_VERBOSE}
3565    !define ${_MOZFUNC_UN}DeleteRelativeProfiles "!insertmacro ${_MOZFUNC_UN}DeleteRelativeProfilesCall"
3566
3567    Function ${_MOZFUNC_UN}DeleteRelativeProfiles
3568      Exch $R9
3569      Push $R8
3570      Push $R7
3571      Push $R6
3572
3573      SetShellVarContext current
3574      StrCpy $R8 -1
3575
3576      loop:
3577      IntOp $R8 $R8 + 1  ; Increment the counter.
3578      ReadINIStr $R7 "$APPDATA\$R9\profiles.ini" "Profile$R8" "Path"
3579      IfErrors end +1
3580
3581      ; Only remove relative profiles
3582      ReadINIStr $R6 "$APPDATA\$R9\profiles.ini" "Profile$R8" "IsRelative"
3583      StrCmp "$R6" "1" +1 loop
3584
3585      ; Relative paths in profiles.ini use / as a separator
3586      ${${_MOZFUNC_UN}WordReplace} "$R7" "/" "\" "+" $R7
3587
3588      IfFileExists "$LOCALAPPDATA\$R9\$R7" +1 +2
3589      RmDir /r "$LOCALAPPDATA\$R9\$R7"
3590      IfFileExists "$APPDATA\$R9\$R7" +1 +2
3591      RmDir /r "$APPDATA\$R9\$R7"
3592      GoTo loop
3593
3594      end:
3595      ; Remove profiles directory under LOCALAPPDATA (e.g. cache, etc.) since
3596      ; they are at times abandoned.
3597      RmDir /r "$LOCALAPPDATA\$R9\Profiles"
3598      RmDir /r "$APPDATA\$R9\Crash Reports"
3599      Delete "$APPDATA\$R9\profiles.ini"
3600      Delete "$APPDATA\$R9\console.log"
3601      Delete "$APPDATA\$R9\pluginreg.dat"
3602      RmDir "$APPDATA\$R9\Profiles"
3603      RmDir "$APPDATA\$R9"
3604
3605      Pop $R6
3606      Pop $R7
3607      Pop $R8
3608      Exch $R9
3609    FunctionEnd
3610
3611    !verbose pop
3612  !endif
3613!macroend
3614
3615!macro DeleteRelativeProfilesCall _REL_PROFILE_PATH
3616  !verbose push
3617  !verbose ${_MOZFUNC_VERBOSE}
3618  Push "${_REL_PROFILE_PATH}"
3619  Call DeleteRelativeProfiles
3620  !verbose pop
3621!macroend
3622
3623!macro un.DeleteRelativeProfilesCall _REL_PROFILE_PATH
3624  !verbose push
3625  !verbose ${_MOZFUNC_VERBOSE}
3626  Push "${_REL_PROFILE_PATH}"
3627  Call un.DeleteRelativeProfiles
3628  !verbose pop
3629!macroend
3630
3631!macro un.DeleteRelativeProfiles
3632  !ifndef un.DeleteRelativeProfiles
3633    !verbose push
3634    !verbose ${_MOZFUNC_VERBOSE}
3635    !undef _MOZFUNC_UN
3636    !define _MOZFUNC_UN "un."
3637
3638    !insertmacro DeleteRelativeProfiles
3639
3640    !undef _MOZFUNC_UN
3641    !define _MOZFUNC_UN
3642    !verbose pop
3643  !endif
3644!macroend
3645
3646/**
3647 * Deletes shortcuts and Start Menu directories under Programs as specified by
3648 * the shortcuts log ini file and on Windows 7 unpins TaskBar and Start Menu
3649 * shortcuts. The shortcuts will not be deleted if the shortcut target isn't for
3650 * this install location which is determined by the shortcut having a target of
3651 * $INSTDIR\${FileMainEXE}. The context (All Users or Current User) of the
3652 * $DESKTOP and $SMPROGRAMS constants depends on the
3653 * SetShellVarContext setting and must be set by the caller of this macro. There
3654 * is no All Users context for $QUICKLAUNCH but this will not cause a problem
3655 * since the macro will just continue past the $QUICKLAUNCH shortcut deletion
3656 * section on subsequent calls.
3657 *
3658 * The ini file sections must have the following format (the order of the
3659 * sections in the ini file is not important):
3660 * [SMPROGRAMS]
3661 * ; RelativePath is the directory relative from the Start Menu
3662 * ; Programs directory.
3663 * RelativePath=Mozilla App
3664 * ; Shortcut1 is the first shortcut, Shortcut2 is the second shortcut, and so
3665 * ; on. There must not be a break in the sequence of the numbers.
3666 * Shortcut1=Mozilla App.lnk
3667 * Shortcut2=Mozilla App (Safe Mode).lnk
3668 * [DESKTOP]
3669 * ; Shortcut1 is the first shortcut, Shortcut2 is the second shortcut, and so
3670 * ; on. There must not be a break in the sequence of the numbers.
3671 * Shortcut1=Mozilla App.lnk
3672 * Shortcut2=Mozilla App (Safe Mode).lnk
3673 * [QUICKLAUNCH]
3674 * ; Shortcut1 is the first shortcut, Shortcut2 is the second shortcut, and so
3675 * ; on. There must not be a break in the sequence of the numbers for the
3676 * ; suffix.
3677 * Shortcut1=Mozilla App.lnk
3678 * Shortcut2=Mozilla App (Safe Mode).lnk
3679 * [STARTMENU]
3680 * ; Shortcut1 is the first shortcut, Shortcut2 is the second shortcut, and so
3681 * ; on. There must not be a break in the sequence of the numbers for the
3682 * ; suffix.
3683 * Shortcut1=Mozilla App.lnk
3684 * Shortcut2=Mozilla App (Safe Mode).lnk
3685 *
3686 * $R4 = counter for appending to Shortcut for enumerating the ini file entries
3687 * $R5 = return value from ShellLink::GetShortCutTarget and
3688 *       ApplicationID::UninstallPinnedItem
3689 * $R6 = find handle and the long path to the Start Menu Programs directory
3690 *       (e.g. $SMPROGRAMS)
3691 * $R7 = path to the $QUICKLAUNCH\User Pinned directory and the return value
3692 *       from ReadINIStr for the relative path to the applications directory
3693 *       under the Start Menu Programs directory and the long path to this
3694 *       directory
3695 * $R8 = return filename from FindFirst / FindNext and the return value from
3696 *       ReadINIStr for enumerating shortcuts
3697 * $R9 = long path to the shortcuts log ini file
3698 */
3699!macro DeleteShortcuts
3700
3701  !ifndef ${_MOZFUNC_UN}DeleteShortcuts
3702    !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN}
3703    !insertmacro ${_MOZFUNC_UN_TMP}GetLongPath
3704    !insertmacro ${_MOZFUNC_UN_TMP}GetParent
3705    !undef _MOZFUNC_UN
3706    !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP}
3707    !undef _MOZFUNC_UN_TMP
3708
3709    !verbose push
3710    !verbose ${_MOZFUNC_VERBOSE}
3711    !define ${_MOZFUNC_UN}DeleteShortcuts "!insertmacro ${_MOZFUNC_UN}DeleteShortcutsCall"
3712
3713    Function ${_MOZFUNC_UN}DeleteShortcuts
3714      Push $R9
3715      Push $R8
3716      Push $R7
3717      Push $R6
3718      Push $R5
3719      Push $R4
3720
3721      ${If} ${AtLeastWin7}
3722        ; Since shortcuts that are pinned can later be removed without removing
3723        ; the pinned shortcut unpin the pinned shortcuts for the application's
3724        ; main exe using the pinned shortcuts themselves.
3725        StrCpy $R7 "$QUICKLAUNCH\User Pinned"
3726
3727        ${If} ${FileExists} "$R7\TaskBar"
3728          ; Delete TaskBar pinned shortcuts for the application's main exe
3729          FindFirst $R6 $R8 "$R7\TaskBar\*.lnk"
3730          ${Do}
3731            ${If} ${FileExists} "$R7\TaskBar\$R8"
3732              ShellLink::GetShortCutTarget "$R7\TaskBar\$R8"
3733              Pop $R5
3734              ${${_MOZFUNC_UN}GetLongPath} "$R5" $R5
3735              ${If} "$R5" == "$INSTDIR\${FileMainEXE}"
3736                ApplicationID::UninstallPinnedItem "$R7\TaskBar\$R8"
3737                Pop $R5
3738              ${EndIf}
3739            ${EndIf}
3740            ClearErrors
3741            FindNext $R6 $R8
3742            ${If} ${Errors}
3743              ${ExitDo}
3744            ${EndIf}
3745          ${Loop}
3746          FindClose $R6
3747        ${EndIf}
3748
3749        ${If} ${FileExists} "$R7\StartMenu"
3750          ; Delete Start Menu pinned shortcuts for the application's main exe
3751          FindFirst $R6 $R8 "$R7\StartMenu\*.lnk"
3752          ${Do}
3753            ${If} ${FileExists} "$R7\StartMenu\$R8"
3754              ShellLink::GetShortCutTarget "$R7\StartMenu\$R8"
3755              Pop $R5
3756              ${${_MOZFUNC_UN}GetLongPath} "$R5" $R5
3757              ${If} "$R5" == "$INSTDIR\${FileMainEXE}"
3758                  ApplicationID::UninstallPinnedItem "$R7\StartMenu\$R8"
3759                  Pop $R5
3760              ${EndIf}
3761            ${EndIf}
3762            ClearErrors
3763            FindNext $R6 $R8
3764            ${If} ${Errors}
3765              ${ExitDo}
3766            ${EndIf}
3767          ${Loop}
3768          FindClose $R6
3769        ${EndIf}
3770      ${EndIf}
3771
3772      ; Don't call ApplicationID::UninstallPinnedItem since pinned items for
3773      ; this application were removed above and removing them below will remove
3774      ; the association of side by side installations.
3775      ${${_MOZFUNC_UN}GetLongPath} "$INSTDIR\uninstall\${SHORTCUTS_LOG}" $R9
3776      ${If} ${FileExists} "$R9"
3777        ; Delete Start Menu shortcuts for this application
3778        StrCpy $R4 -1
3779        ${Do}
3780          IntOp $R4 $R4 + 1 ; Increment the counter
3781          ClearErrors
3782          ReadINIStr $R8 "$R9" "STARTMENU" "Shortcut$R4"
3783          ${If} ${Errors}
3784            ${ExitDo}
3785          ${EndIf}
3786
3787          ${If} ${FileExists} "$SMPROGRAMS\$R8"
3788            ShellLink::GetShortCutTarget "$SMPROGRAMS\$R8"
3789            Pop $R5
3790            ${${_MOZFUNC_UN}GetLongPath} "$R5" $R5
3791            ${If} "$INSTDIR\${FileMainEXE}" == "$R5"
3792              Delete "$SMPROGRAMS\$R8"
3793            ${EndIf}
3794          ${EndIf}
3795        ${Loop}
3796
3797        ; Delete Quick Launch shortcuts for this application
3798        StrCpy $R4 -1
3799        ${Do}
3800          IntOp $R4 $R4 + 1 ; Increment the counter
3801          ClearErrors
3802          ReadINIStr $R8 "$R9" "QUICKLAUNCH" "Shortcut$R4"
3803          ${If} ${Errors}
3804            ${ExitDo}
3805          ${EndIf}
3806
3807          ${If} ${FileExists} "$QUICKLAUNCH\$R8"
3808            ShellLink::GetShortCutTarget "$QUICKLAUNCH\$R8"
3809            Pop $R5
3810            ${${_MOZFUNC_UN}GetLongPath} "$R5" $R5
3811            ${If} "$INSTDIR\${FileMainEXE}" == "$R5"
3812              Delete "$QUICKLAUNCH\$R8"
3813            ${EndIf}
3814          ${EndIf}
3815        ${Loop}
3816
3817        ; Delete Desktop shortcuts for this application
3818        StrCpy $R4 -1
3819        ${Do}
3820          IntOp $R4 $R4 + 1 ; Increment the counter
3821          ClearErrors
3822          ReadINIStr $R8 "$R9" "DESKTOP" "Shortcut$R4"
3823          ${If} ${Errors}
3824            ${ExitDo}
3825          ${EndIf}
3826
3827          ${If} ${FileExists} "$DESKTOP\$R8"
3828            ShellLink::GetShortCutTarget "$DESKTOP\$R8"
3829            Pop $R5
3830            ${${_MOZFUNC_UN}GetLongPath} "$R5" $R5
3831            ${If} "$INSTDIR\${FileMainEXE}" == "$R5"
3832              Delete "$DESKTOP\$R8"
3833            ${EndIf}
3834          ${EndIf}
3835        ${Loop}
3836
3837        ${${_MOZFUNC_UN}GetLongPath} "$SMPROGRAMS" $R6
3838
3839        ; Delete Start Menu Programs shortcuts for this application
3840        ClearErrors
3841        ReadINIStr $R7 "$R9" "SMPROGRAMS" "RelativePathToDir"
3842        ${${_MOZFUNC_UN}GetLongPath} "$R6\$R7" $R7
3843        ${Unless} "$R7" == ""
3844          StrCpy $R4 -1
3845          ${Do}
3846            IntOp $R4 $R4 + 1 ; Increment the counter
3847            ClearErrors
3848            ReadINIStr $R8 "$R9" "SMPROGRAMS" "Shortcut$R4"
3849            ${If} ${Errors}
3850              ${ExitDo}
3851            ${EndIf}
3852
3853            ${If} ${FileExists} "$R7\$R8"
3854              ShellLink::GetShortCutTarget "$R7\$R8"
3855              Pop $R5
3856              ${${_MOZFUNC_UN}GetLongPath} "$R5" $R5
3857              ${If} "$INSTDIR\${FileMainEXE}" == "$R5"
3858                Delete "$R7\$R8"
3859              ${EndIf}
3860            ${EndIf}
3861          ${Loop}
3862
3863          ; Delete Start Menu Programs directories for this application
3864          ${Do}
3865            ClearErrors
3866            ${If} "$R6" == "$R7"
3867              ${ExitDo}
3868            ${EndIf}
3869            RmDir "$R7"
3870            ${If} ${Errors}
3871              ${ExitDo}
3872            ${EndIf}
3873            ${${_MOZFUNC_UN}GetParent} "$R7" $R7
3874          ${Loop}
3875        ${EndUnless}
3876      ${EndIf}
3877
3878      ClearErrors
3879
3880      Pop $R4
3881      Pop $R5
3882      Pop $R6
3883      Pop $R7
3884      Pop $R8
3885      Pop $R9
3886    FunctionEnd
3887
3888    !verbose pop
3889  !endif
3890!macroend
3891
3892!macro DeleteShortcutsCall
3893  !verbose push
3894  !verbose ${_MOZFUNC_VERBOSE}
3895  Call DeleteShortcuts
3896  !verbose pop
3897!macroend
3898
3899!macro un.DeleteShortcutsCall
3900  !verbose push
3901  !verbose ${_MOZFUNC_VERBOSE}
3902  Call un.DeleteShortcuts
3903  !verbose pop
3904!macroend
3905
3906!macro un.DeleteShortcuts
3907  !ifndef un.DeleteShortcuts
3908    !verbose push
3909    !verbose ${_MOZFUNC_VERBOSE}
3910    !undef _MOZFUNC_UN
3911    !define _MOZFUNC_UN "un."
3912
3913    !insertmacro DeleteShortcuts
3914
3915    !undef _MOZFUNC_UN
3916    !define _MOZFUNC_UN
3917    !verbose pop
3918  !endif
3919!macroend
3920
3921
3922################################################################################
3923# Macros for parsing and updating the uninstall.log
3924
3925/**
3926 * Updates the uninstall.log with new files added by software update.
3927 *
3928 * When modifying this macro be aware that LineFind uses all registers except
3929 * $R0-$R3 and TextCompareNoDetails uses all registers except $R0-$R9 so be
3930 * cautious. Callers of this macro are not affected.
3931 */
3932!macro UpdateUninstallLog
3933
3934  !ifndef UpdateUninstallLog
3935    !insertmacro FileJoin
3936    !insertmacro LineFind
3937    !insertmacro TextCompareNoDetails
3938    !insertmacro TrimNewLines
3939
3940    !verbose push
3941    !verbose ${_MOZFUNC_VERBOSE}
3942    !define UpdateUninstallLog "!insertmacro UpdateUninstallLogCall"
3943
3944    Function UpdateUninstallLog
3945      Push $R3
3946      Push $R2
3947      Push $R1
3948      Push $R0
3949
3950      ClearErrors
3951
3952      GetFullPathName $R3 "$INSTDIR\uninstall"
3953      ${If} ${FileExists} "$R3\uninstall.update"
3954        ${LineFind} "$R3\uninstall.update" "" "1:-1" "CleanupUpdateLog"
3955
3956        GetTempFileName $R2 "$R3"
3957        FileOpen $R1 "$R2" w
3958        ${TextCompareNoDetails} "$R3\uninstall.update" "$R3\uninstall.log" "SlowDiff" "CreateUpdateDiff"
3959        FileClose $R1
3960
3961        IfErrors +2 0
3962        ${FileJoin} "$R3\uninstall.log" "$R2" "$R3\uninstall.log"
3963
3964        ${DeleteFile} "$R2"
3965      ${EndIf}
3966
3967      ClearErrors
3968
3969      Pop $R0
3970      Pop $R1
3971      Pop $R2
3972      Pop $R3
3973    FunctionEnd
3974
3975    ; This callback MUST use labels vs. relative line numbers.
3976    Function CleanupUpdateLog
3977      StrCpy $R2 "$R9" 12
3978      StrCmp "$R2" "EXECUTE ADD " +1 skip
3979      StrCpy $R9 "$R9" "" 12
3980
3981      Push $R6
3982      Push $R5
3983      Push $R4
3984      StrCpy $R4 ""         ; Initialize to an empty string.
3985      StrCpy $R6 -1         ; Set the counter to -1 so it will start at 0.
3986
3987      loop:
3988      IntOp $R6 $R6 + 1     ; Increment the counter.
3989      StrCpy $R5 $R9 1 $R6  ; Starting from the counter copy the next char.
3990      StrCmp $R5 "" copy    ; Are there no more chars?
3991      StrCmp $R5 "/" +1 +2  ; Is the char a /?
3992      StrCpy $R5 "\"        ; Replace the char with a \.
3993
3994      StrCpy $R4 "$R4$R5"
3995      GoTo loop
3996
3997      copy:
3998      StrCpy $R9 "File: \$R4"
3999      Pop $R6
4000      Pop $R5
4001      Pop $R4
4002      GoTo end
4003
4004      skip:
4005      StrCpy $0 "SkipWrite"
4006
4007      end:
4008      Push $0
4009    FunctionEnd
4010
4011    Function CreateUpdateDiff
4012      ${TrimNewLines} "$9" $9
4013      ${If} $9 != ""
4014        FileWrite $R1 "$9$\r$\n"
4015      ${EndIf}
4016
4017      Push 0
4018    FunctionEnd
4019
4020    !verbose pop
4021  !endif
4022!macroend
4023
4024!macro UpdateUninstallLogCall
4025  !verbose push
4026  !verbose ${_MOZFUNC_VERBOSE}
4027  Call UpdateUninstallLog
4028  !verbose pop
4029!macroend
4030
4031/**
4032 * Copies files from a source directory to a destination directory with logging
4033 * to the uninstall.log. If any destination files are in use a reboot will be
4034 * necessary to complete the installation and the reboot flag (see IfRebootFlag
4035 * in the NSIS documentation).
4036 *
4037 * @param   _PATH_TO_SOURCE
4038 *          Source path to copy the files from. This must not end with a \.
4039 *
4040 * @param   _PATH_TO_DESTINATION
4041 *          Destination path to copy the files to. This must not end with a \.
4042 *
4043 * @param   _PREFIX_ERROR_CREATEDIR
4044 *          Prefix for the directory creation error message. The directory path
4045 *          will be inserted below this string.
4046 *
4047 * @param   _SUFFIX_ERROR_CREATEDIR
4048 *          Suffix for the directory creation error message. The directory path
4049 *          will be inserted above this string.
4050 *
4051 * $0  = destination file's parent directory used in the create_dir label
4052 * $R0 = copied value from $R6 (e.g. _PATH_TO_SOURCE)
4053 * $R1 = copied value from $R7 (e.g. _PATH_TO_DESTINATION)
4054 * $R2 = string length of the path to source
4055 * $R3 = relative path from the path to source
4056 * $R4 = copied value from $R8 (e.g. _PREFIX_ERROR_CREATEDIR)
4057 * $R5 = copied value from $R9 (e.g. _SUFFIX_ERROR_CREATEDIR)
4058 * note: the LocateNoDetails macro uses these registers so we copy the values
4059 *       to other registers.
4060 * $R6 = initially _PATH_TO_SOURCE and then set to "size" ($R6="" if directory,
4061 *       $R6="0" if file with /S=)"path\name" in callback
4062 * $R7 = initially _PATH_TO_DESTINATION and then set to "name" in callback
4063 * $R8 = initially _PREFIX_ERROR_CREATEDIR and then set to "path" in callback
4064 * $R9 = initially _SUFFIX_ERROR_CREATEDIR and then set to "path\name" in
4065 *       callback
4066 */
4067!macro CopyFilesFromDir
4068
4069  !ifndef CopyFilesFromDir
4070    !insertmacro LocateNoDetails
4071    !insertmacro OnEndCommon
4072    !insertmacro WordReplace
4073
4074    !verbose push
4075    !verbose ${_MOZFUNC_VERBOSE}
4076    !define CopyFilesFromDir "!insertmacro CopyFilesFromDirCall"
4077
4078    Function CopyFilesFromDir
4079      Exch $R9
4080      Exch 1
4081      Exch $R8
4082      Exch 2
4083      Exch $R7
4084      Exch 3
4085      Exch $R6
4086      Push $R5
4087      Push $R4
4088      Push $R3
4089      Push $R2
4090      Push $R1
4091      Push $R0
4092      Push $0
4093
4094      StrCpy $R0 "$R6"
4095      StrCpy $R1 "$R7"
4096      StrCpy $R4 "$R8"
4097      StrCpy $R5 "$R9"
4098
4099      StrLen $R2 "$R0"
4100
4101      ${LocateNoDetails} "$R0" "/L=FD" "CopyFileCallback"
4102
4103      Pop $0
4104      Pop $R0
4105      Pop $R1
4106      Pop $R2
4107      Pop $R3
4108      Pop $R4
4109      Pop $R5
4110      Exch $R6
4111      Exch 3
4112      Exch $R7
4113      Exch 2
4114      Exch $R8
4115      Exch 1
4116      Exch $R9
4117    FunctionEnd
4118
4119    Function CopyFileCallback
4120      StrCpy $R3 $R8 "" $R2 ; $R3 always begins with a \.
4121
4122      retry:
4123      ClearErrors
4124      StrCmp $R6 "" +1 copy_file
4125      IfFileExists "$R1$R3\$R7" end +1
4126      StrCpy $0 "$R1$R3\$R7"
4127
4128      create_dir:
4129      ClearErrors
4130      CreateDirectory "$0"
4131      IfFileExists "$0" +1 err_create_dir  ; protect against looping.
4132      ${LogMsg} "Created Directory: $0"
4133      StrCmp $R6 "" end copy_file
4134
4135      err_create_dir:
4136      ${LogMsg} "** ERROR Creating Directory: $0 **"
4137      MessageBox MB_RETRYCANCEL|MB_ICONQUESTION "$R4$\r$\n$\r$\n$0$\r$\n$\r$\n$R5" IDRETRY retry
4138      ${OnEndCommon}
4139      Quit
4140
4141      copy_file:
4142      StrCpy $0 "$R1$R3"
4143      StrCmp "$0" "$INSTDIR" +2 +1
4144      IfFileExists "$0" +1 create_dir
4145
4146      ClearErrors
4147      ${DeleteFile} "$R1$R3\$R7"
4148      IfErrors +1 dest_clear
4149      ClearErrors
4150      Rename "$R1$R3\$R7" "$R1$R3\$R7.moz-delete"
4151      IfErrors +1 reboot_delete
4152
4153      ; file will replace destination file on reboot
4154      Rename "$R9" "$R9.moz-upgrade"
4155      CopyFiles /SILENT "$R9.moz-upgrade" "$R1$R3"
4156      Rename /REBOOTOK "$R1$R3\$R7.moz-upgrade" "$R1$R3\$R7"
4157      ${LogMsg} "Copied File: $R1$R3\$R7.moz-upgrade"
4158      ${LogMsg} "Delayed Install File (Reboot Required): $R1$R3\$R7"
4159      GoTo log_uninstall
4160
4161      ; file will be deleted on reboot
4162      reboot_delete:
4163      CopyFiles /SILENT $R9 "$R1$R3"
4164      Delete /REBOOTOK "$R1$R3\$R7.moz-delete"
4165      ${LogMsg} "Installed File: $R1$R3\$R7"
4166      ${LogMsg} "Delayed Delete File (Reboot Required): $R1$R3\$R7.moz-delete"
4167      GoTo log_uninstall
4168
4169      ; destination file doesn't exist - coast is clear
4170      dest_clear:
4171      CopyFiles /SILENT $R9 "$R1$R3"
4172      ${LogMsg} "Installed File: $R1$R3\$R7"
4173
4174      log_uninstall:
4175      ; If the file is installed into the installation directory remove the
4176      ; installation directory's path from the file path when writing to the
4177      ; uninstall.log so it will be a relative path. This allows the same
4178      ; helper.exe to be used with zip builds if we supply an uninstall.log.
4179      ${WordReplace} "$R1$R3\$R7" "$INSTDIR" "" "+" $R3
4180      ${LogUninstall} "File: $R3"
4181
4182      end:
4183      Push 0
4184    FunctionEnd
4185
4186    !verbose pop
4187  !endif
4188!macroend
4189
4190!macro CopyFilesFromDirCall _PATH_TO_SOURCE _PATH_TO_DESTINATION \
4191                            _PREFIX_ERROR_CREATEDIR _SUFFIX_ERROR_CREATEDIR
4192  !verbose push
4193  !verbose ${_MOZFUNC_VERBOSE}
4194  Push "${_PATH_TO_SOURCE}"
4195  Push "${_PATH_TO_DESTINATION}"
4196  Push "${_PREFIX_ERROR_CREATEDIR}"
4197  Push "${_SUFFIX_ERROR_CREATEDIR}"
4198  Call CopyFilesFromDir
4199  !verbose pop
4200!macroend
4201
4202/**
4203 * Parses the uninstall.log on install to first remove a previous installation's
4204 * files and then their directories if empty prior to installing.
4205 *
4206 * When modifying this macro be aware that LineFind uses all registers except
4207 * $R0-$R3 so be cautious. Callers of this macro are not affected.
4208 */
4209!macro OnInstallUninstall
4210
4211  !ifndef OnInstallUninstall
4212    !insertmacro GetParent
4213    !insertmacro LineFind
4214    !insertmacro TrimNewLines
4215
4216    !verbose push
4217    !verbose ${_MOZFUNC_VERBOSE}
4218    !define OnInstallUninstall "!insertmacro OnInstallUninstallCall"
4219
4220    Function OnInstallUninstall
4221      Push $R9
4222      Push $R8
4223      Push $R7
4224      Push $R6
4225      Push $R5
4226      Push $R4
4227      Push $R3
4228      Push $R2
4229      Push $R1
4230      Push $R0
4231      Push $TmpVal
4232
4233      IfFileExists "$INSTDIR\uninstall\uninstall.log" +1 end
4234
4235      ${LogHeader} "Removing Previous Installation"
4236
4237      ; Copy the uninstall log file to a temporary file
4238      GetTempFileName $TmpVal
4239      CopyFiles /SILENT /FILESONLY "$INSTDIR\uninstall\uninstall.log" "$TmpVal"
4240
4241      ; Delete files
4242      ${LineFind} "$TmpVal" "/NUL" "1:-1" "RemoveFilesCallback"
4243
4244      ; Remove empty directories
4245      ${LineFind} "$TmpVal" "/NUL" "1:-1" "RemoveDirsCallback"
4246
4247      ; Delete the temporary uninstall log file
4248      Delete /REBOOTOK "$TmpVal"
4249
4250      ; Delete the uninstall log file
4251      Delete "$INSTDIR\uninstall\uninstall.log"
4252
4253      end:
4254      ClearErrors
4255
4256      Pop $TmpVal
4257      Pop $R0
4258      Pop $R1
4259      Pop $R2
4260      Pop $R3
4261      Pop $R4
4262      Pop $R5
4263      Pop $R6
4264      Pop $R7
4265      Pop $R8
4266      Pop $R9
4267    FunctionEnd
4268
4269    Function RemoveFilesCallback
4270      ${TrimNewLines} "$R9" $R9
4271      StrCpy $R1 "$R9" 5       ; Copy the first five chars
4272
4273      StrCmp "$R1" "File:" +1 end
4274      StrCpy $R9 "$R9" "" 6    ; Copy string starting after the 6th char
4275      StrCpy $R0 "$R9" 1       ; Copy the first char
4276
4277      StrCmp "$R0" "\" +1 end  ; If this isn't a relative path goto end
4278      StrCmp "$R9" "\install.log" end +1 ; Skip the install.log
4279      StrCmp "$R9" "\MapiProxy_InUse.dll" end +1 ; Skip the MapiProxy_InUse.dll
4280      StrCmp "$R9" "\mozMapi32_InUse.dll" end +1 ; Skip the mozMapi32_InUse.dll
4281
4282      StrCpy $R1 "$INSTDIR$R9" ; Copy the install dir path and suffix it with the string
4283      IfFileExists "$R1" +1 end
4284
4285      ClearErrors
4286      Delete "$R1"
4287      ${Unless} ${Errors}
4288        ${LogMsg} "Deleted File: $R1"
4289        Goto end
4290      ${EndUnless}
4291
4292      ClearErrors
4293      Rename "$R1" "$R1.moz-delete"
4294      ${Unless} ${Errors}
4295        Delete /REBOOTOK "$R1.moz-delete"
4296        ${LogMsg} "Delayed Delete File (Reboot Required): $R1.moz-delete"
4297        GoTo end
4298      ${EndUnless}
4299
4300      ; Check if the file exists in the source. If it does the new file will
4301      ; replace the existing file when the system is rebooted. If it doesn't
4302      ; the file will be deleted when the system is rebooted.
4303      ${Unless} ${FileExists} "$EXEDIR\core$R9"
4304      ${AndUnless}  ${FileExists} "$EXEDIR\optional$R9"
4305        Delete /REBOOTOK "$R1"
4306        ${LogMsg} "Delayed Delete File (Reboot Required): $R1"
4307      ${EndUnless}
4308
4309      end:
4310      ClearErrors
4311
4312      Push 0
4313    FunctionEnd
4314
4315    ; Using locate will leave file handles open to some of the directories
4316    ; which will prevent the deletion of these directories. This parses the
4317    ; uninstall.log and uses the file entries to find / remove empty
4318    ; directories.
4319    Function RemoveDirsCallback
4320      ${TrimNewLines} "$R9" $R9
4321      StrCpy $R0 "$R9" 5          ; Copy the first five chars
4322      StrCmp "$R0" "File:" +1 end
4323
4324      StrCpy $R9 "$R9" "" 6       ; Copy string starting after the 6th char
4325      StrCpy $R0 "$R9" 1          ; Copy the first char
4326
4327      StrCpy $R1 "$INSTDIR$R9"    ; Copy the install dir path and suffix it with the string
4328      StrCmp "$R0" "\" loop end   ; If this isn't a relative path goto end
4329
4330      loop:
4331      ${GetParent} "$R1" $R1         ; Get the parent directory for the path
4332      StrCmp "$R1" "$INSTDIR" end +1 ; If the directory is the install dir goto end
4333
4334      IfFileExists "$R1" +1 loop  ; Only try to remove the dir if it exists
4335      ClearErrors
4336      RmDir "$R1"     ; Remove the dir
4337      IfErrors end +1  ; If we fail there is no use trying to remove its parent dir
4338      ${LogMsg} "Deleted Directory: $R1"
4339      GoTo loop
4340
4341      end:
4342      ClearErrors
4343
4344      Push 0
4345    FunctionEnd
4346
4347    !verbose pop
4348  !endif
4349!macroend
4350
4351!macro OnInstallUninstallCall
4352  !verbose push
4353  !verbose ${_MOZFUNC_VERBOSE}
4354  Call OnInstallUninstall
4355  !verbose pop
4356!macroend
4357
4358/**
4359 * Parses the precomplete file to remove an installation's files and
4360 * directories.
4361 *
4362 * @param   _CALLBACK
4363 *          The function address of a callback function for progress or "false"
4364 *          if there is no callback function.
4365 *
4366 * $R3 = false if all files were deleted or moved to the tobedeleted directory.
4367 *       true if file(s) could not be moved to the tobedeleted directory.
4368 * $R4 = Path to temporary precomplete file.
4369 * $R5 = File handle for the temporary precomplete file.
4370 * $R6 = String returned from FileRead.
4371 * $R7 = First seven characters of the string returned from FileRead.
4372 * $R8 = Temporary file path used to rename files that are in use.
4373 * $R9 = _CALLBACK
4374 */
4375!macro RemovePrecompleteEntries
4376
4377  !ifndef ${_MOZFUNC_UN}RemovePrecompleteEntries
4378    !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN}
4379    !insertmacro ${_MOZFUNC_UN_TMP}GetParent
4380    !insertmacro ${_MOZFUNC_UN_TMP}TrimNewLines
4381    !insertmacro ${_MOZFUNC_UN_TMP}WordReplace
4382    !undef _MOZFUNC_UN
4383    !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP}
4384    !undef _MOZFUNC_UN_TMP
4385
4386    !verbose push
4387    !verbose ${_MOZFUNC_VERBOSE}
4388    !define ${_MOZFUNC_UN}RemovePrecompleteEntries "!insertmacro ${_MOZFUNC_UN}RemovePrecompleteEntriesCall"
4389
4390    Function ${_MOZFUNC_UN}RemovePrecompleteEntries
4391      Exch $R9
4392      Push $R8
4393      Push $R7
4394      Push $R6
4395      Push $R5
4396      Push $R4
4397      Push $R3
4398
4399      ${If} ${FileExists} "$INSTDIR\precomplete"
4400        StrCpy $R3 "false"
4401
4402        RmDir /r "$INSTDIR\${TO_BE_DELETED}"
4403        CreateDirectory "$INSTDIR\${TO_BE_DELETED}"
4404        GetTempFileName $R4 "$INSTDIR\${TO_BE_DELETED}"
4405        Delete "$R4"
4406        Rename "$INSTDIR\precomplete" "$R4"
4407
4408        ClearErrors
4409        ; Rename and then remove files
4410        FileOpen $R5 "$R4" r
4411        ${Do}
4412          FileRead $R5 $R6
4413          ${If} ${Errors}
4414            ${Break}
4415          ${EndIf}
4416
4417          ${${_MOZFUNC_UN}TrimNewLines} "$R6" $R6
4418          ; Replace all occurrences of "/" with "\".
4419          ${${_MOZFUNC_UN}WordReplace} "$R6" "/" "\" "+" $R6
4420
4421          ; Copy the first 7 chars
4422          StrCpy $R7 "$R6" 7
4423          ${If} "$R7" == "remove "
4424            ; Copy the string starting after the 8th char
4425            StrCpy $R6 "$R6" "" 8
4426            ; Copy all but the last char to remove the double quote.
4427            StrCpy $R6 "$R6" -1
4428            ${If} ${FileExists} "$INSTDIR\$R6"
4429              ${Unless} "$R9" == "false"
4430                Call $R9
4431              ${EndUnless}
4432
4433              ClearErrors
4434              Delete "$INSTDIR\$R6"
4435              ${If} ${Errors}
4436                GetTempFileName $R8 "$INSTDIR\${TO_BE_DELETED}"
4437                Delete "$R8"
4438                ClearErrors
4439                Rename "$INSTDIR\$R6" "$R8"
4440                ${Unless} ${Errors}
4441                  Delete /REBOOTOK "$R8"
4442
4443                  ClearErrors
4444                ${EndUnless}
4445!ifdef __UNINSTALL__
4446                ${If} ${Errors}
4447                  Delete /REBOOTOK "$INSTDIR\$R6"
4448                  StrCpy $R3 "true"
4449                  ClearErrors
4450                ${EndIf}
4451!endif
4452              ${EndIf}
4453            ${EndIf}
4454          ${ElseIf} "$R7" == "rmdir $\""
4455            ; Copy the string starting after the 7th char.
4456            StrCpy $R6 "$R6" "" 7
4457            ; Copy all but the last two chars to remove the slash and the double quote.
4458            StrCpy $R6 "$R6" -2
4459            ${If} ${FileExists} "$INSTDIR\$R6"
4460              ; Ignore directory removal errors
4461              RmDir "$INSTDIR\$R6"
4462              ClearErrors
4463            ${EndIf}
4464          ${EndIf}
4465        ${Loop}
4466        FileClose $R5
4467
4468        ; Delete the temporary precomplete file
4469        Delete /REBOOTOK "$R4"
4470
4471        RmDir /r /REBOOTOK "$INSTDIR\${TO_BE_DELETED}"
4472
4473        ${If} ${RebootFlag}
4474        ${AndIf} "$R3" == "false"
4475          ; Clear the reboot flag if all files were deleted or moved to the
4476          ; tobedeleted directory.
4477          SetRebootFlag false
4478        ${EndIf}
4479      ${EndIf}
4480
4481      ClearErrors
4482
4483      Pop $R3
4484      Pop $R4
4485      Pop $R5
4486      Pop $R6
4487      Pop $R7
4488      Pop $R8
4489      Exch $R9
4490    FunctionEnd
4491
4492    !verbose pop
4493  !endif
4494!macroend
4495
4496!macro RemovePrecompleteEntriesCall _CALLBACK
4497  !verbose push
4498  Push "${_CALLBACK}"
4499  !verbose ${_MOZFUNC_VERBOSE}
4500  Call RemovePrecompleteEntries
4501  !verbose pop
4502!macroend
4503
4504!macro un.RemovePrecompleteEntriesCall _CALLBACK
4505  !verbose push
4506  !verbose ${_MOZFUNC_VERBOSE}
4507  Push "${_CALLBACK}"
4508  Call un.RemovePrecompleteEntries
4509  !verbose pop
4510!macroend
4511
4512!macro un.RemovePrecompleteEntries
4513  !ifndef un.RemovePrecompleteEntries
4514    !verbose push
4515    !verbose ${_MOZFUNC_VERBOSE}
4516    !undef _MOZFUNC_UN
4517    !define _MOZFUNC_UN "un."
4518
4519    !insertmacro RemovePrecompleteEntries
4520
4521    !undef _MOZFUNC_UN
4522    !define _MOZFUNC_UN
4523    !verbose pop
4524  !endif
4525!macroend
4526
4527/**
4528 * Parses the uninstall.log to unregister dll's, remove files, and remove
4529 * empty directories for this installation.
4530 *
4531 * When modifying this macro be aware that LineFind uses all registers except
4532 * $R0-$R3 so be cautious. Callers of this macro are not affected.
4533 */
4534!macro un.ParseUninstallLog
4535
4536  !ifndef un.ParseUninstallLog
4537    !insertmacro un.GetParent
4538    !insertmacro un.LineFind
4539    !insertmacro un.TrimNewLines
4540
4541    !verbose push
4542    !verbose ${_MOZFUNC_VERBOSE}
4543    !define un.ParseUninstallLog "!insertmacro un.ParseUninstallLogCall"
4544
4545    Function un.ParseUninstallLog
4546      Push $R9
4547      Push $R8
4548      Push $R7
4549      Push $R6
4550      Push $R5
4551      Push $R4
4552      Push $R3
4553      Push $R2
4554      Push $R1
4555      Push $R0
4556      Push $TmpVal
4557
4558      IfFileExists "$INSTDIR\uninstall\uninstall.log" +1 end
4559
4560      ; Copy the uninstall log file to a temporary file
4561      GetTempFileName $TmpVal
4562      CopyFiles /SILENT /FILESONLY "$INSTDIR\uninstall\uninstall.log" "$TmpVal"
4563
4564      ; Unregister DLL's
4565      ${un.LineFind} "$TmpVal" "/NUL" "1:-1" "un.UnRegDLLsCallback"
4566
4567      ; Delete files
4568      ${un.LineFind} "$TmpVal" "/NUL" "1:-1" "un.RemoveFilesCallback"
4569
4570      ; Remove empty directories
4571      ${un.LineFind} "$TmpVal" "/NUL" "1:-1" "un.RemoveDirsCallback"
4572
4573      ; Delete the temporary uninstall log file
4574      Delete /REBOOTOK "$TmpVal"
4575
4576      end:
4577
4578      Pop $TmpVal
4579      Pop $R0
4580      Pop $R1
4581      Pop $R2
4582      Pop $R3
4583      Pop $R4
4584      Pop $R5
4585      Pop $R6
4586      Pop $R7
4587      Pop $R8
4588      Pop $R9
4589    FunctionEnd
4590
4591    Function un.RemoveFilesCallback
4592      ${un.TrimNewLines} "$R9" $R9
4593      StrCpy $R1 "$R9" 5
4594
4595      StrCmp "$R1" "File:" +1 end
4596      StrCpy $R9 "$R9" "" 6
4597      StrCpy $R0 "$R9" 1
4598
4599      StrCpy $R1 "$INSTDIR$R9"
4600      StrCmp "$R0" "\" +2 +1
4601      StrCpy $R1 "$R9"
4602
4603      IfFileExists "$R1" +1 end
4604      Delete "$R1"
4605      IfErrors +1 end
4606      ClearErrors
4607      Rename "$R1" "$R1.moz-delete"
4608      IfErrors +1 +3
4609      Delete /REBOOTOK "$R1"
4610      GoTo end
4611
4612      Delete /REBOOTOK "$R1.moz-delete"
4613
4614      end:
4615      ClearErrors
4616
4617      Push 0
4618    FunctionEnd
4619
4620    Function un.UnRegDLLsCallback
4621      ${un.TrimNewLines} "$R9" $R9
4622      StrCpy $R1 "$R9" 7
4623
4624      StrCmp $R1 "DLLReg:" +1 end
4625      StrCpy $R9 "$R9" "" 8
4626      StrCpy $R0 "$R9" 1
4627
4628      StrCpy $R1 "$INSTDIR$R9"
4629      StrCmp $R0 "\" +2 +1
4630      StrCpy $R1 "$R9"
4631
4632      ${UnregisterDLL} $R1
4633
4634      end:
4635      ClearErrors
4636
4637      Push 0
4638    FunctionEnd
4639
4640    ; Using locate will leave file handles open to some of the directories
4641    ; which will prevent the deletion of these directories. This parses the
4642    ; uninstall.log and uses the file entries to find / remove empty
4643    ; directories.
4644    Function un.RemoveDirsCallback
4645      ${un.TrimNewLines} "$R9" $R9
4646      StrCpy $R0 "$R9" 5          ; Copy the first five chars
4647      StrCmp "$R0" "File:" +1 end
4648
4649      StrCpy $R9 "$R9" "" 6       ; Copy string starting after the 6th char
4650      StrCpy $R0 "$R9" 1          ; Copy the first char
4651
4652      StrCpy $R1 "$INSTDIR$R9"    ; Copy the install dir path and suffix it with the string
4653      StrCmp "$R0" "\" loop       ; If this is a relative path goto the loop
4654      StrCpy $R1 "$R9"            ; Already a full path so copy the string
4655
4656      loop:
4657      ${un.GetParent} "$R1" $R1   ; Get the parent directory for the path
4658      StrCmp "$R1" "$INSTDIR" end ; If the directory is the install dir goto end
4659
4660      ; We only try to remove empty directories but the Desktop, StartMenu, and
4661      ; QuickLaunch directories can be empty so guard against removing them.
4662      SetShellVarContext all          ; Set context to all users
4663      StrCmp "$R1" "$DESKTOP" end     ; All users desktop
4664      StrCmp "$R1" "$STARTMENU" end   ; All users start menu
4665
4666      SetShellVarContext current      ; Set context to all users
4667      StrCmp "$R1" "$DESKTOP" end     ; Current user desktop
4668      StrCmp "$R1" "$STARTMENU" end   ; Current user start menu
4669      StrCmp "$R1" "$QUICKLAUNCH" end ; Current user quick launch
4670
4671      IfFileExists "$R1" +1 +3  ; Only try to remove the dir if it exists
4672      ClearErrors
4673      RmDir "$R1"    ; Remove the dir
4674      IfErrors end   ; If we fail there is no use trying to remove its parent dir
4675
4676      StrCmp "$R0" "\" loop end  ; Only loop when the path is relative to the install dir
4677
4678      end:
4679      ClearErrors
4680
4681      Push 0
4682    FunctionEnd
4683
4684    !verbose pop
4685  !endif
4686!macroend
4687
4688!macro un.ParseUninstallLogCall
4689  !verbose push
4690  !verbose ${_MOZFUNC_VERBOSE}
4691  Call un.ParseUninstallLog
4692  !verbose pop
4693!macroend
4694
4695/**
4696 * Finds a valid Start Menu shortcut in the uninstall log and returns the
4697 * relative path from the Start Menu's Programs directory to the shortcut's
4698 * directory.
4699 *
4700 * When modifying this macro be aware that LineFind uses all registers except
4701 * $R0-$R3 so be cautious. Callers of this macro are not affected.
4702 *
4703 * @return  _REL_PATH_TO_DIR
4704 *          The relative path to the application's Start Menu directory from the
4705 *          Start Menu's Programs directory.
4706 */
4707!macro FindSMProgramsDir
4708
4709  !ifndef FindSMProgramsDir
4710    !insertmacro GetParent
4711    !insertmacro LineFind
4712    !insertmacro TrimNewLines
4713
4714    !verbose push
4715    !verbose ${_MOZFUNC_VERBOSE}
4716    !define FindSMProgramsDir "!insertmacro FindSMProgramsDirCall"
4717
4718    Function FindSMProgramsDir
4719      Exch $R3
4720      Push $R2
4721      Push $R1
4722      Push $R0
4723
4724      StrCpy $R3 ""
4725      ${If} ${FileExists} "$INSTDIR\uninstall\uninstall.log"
4726        ${LineFind} "$INSTDIR\uninstall\uninstall.log" "/NUL" "1:-1" "FindSMProgramsDirRelPath"
4727      ${EndIf}
4728      ClearErrors
4729
4730      Pop $R0
4731      Pop $R1
4732      Pop $R2
4733      Exch $R3
4734    FunctionEnd
4735
4736    ; This callback MUST use labels vs. relative line numbers.
4737    Function FindSMProgramsDirRelPath
4738      Push 0
4739      ${TrimNewLines} "$R9" $R9
4740      StrCpy $R4 "$R9" 5
4741
4742      StrCmp "$R4" "File:" +1 end_FindSMProgramsDirRelPath
4743      StrCpy $R9 "$R9" "" 6
4744      StrCpy $R4 "$R9" 1
4745
4746      StrCmp "$R4" "\" end_FindSMProgramsDirRelPath +1
4747
4748      SetShellVarContext all
4749      ${GetLongPath} "$SMPROGRAMS" $R4
4750      StrLen $R2 "$R4"
4751      StrCpy $R1 "$R9" $R2
4752      StrCmp "$R1" "$R4" +1 end_FindSMProgramsDirRelPath
4753      IfFileExists "$R9" +1 end_FindSMProgramsDirRelPath
4754      ShellLink::GetShortCutTarget "$R9"
4755      Pop $R0
4756      StrCmp "$INSTDIR\${FileMainEXE}" "$R0" +1 end_FindSMProgramsDirRelPath
4757      ${GetParent} "$R9" $R3
4758      IntOp $R2 $R2 + 1
4759      StrCpy $R3 "$R3" "" $R2
4760
4761      Pop $R4             ; Remove the previously pushed 0 from the stack and
4762      push "StopLineFind" ; push StopLineFind to stop finding more lines.
4763
4764      end_FindSMProgramsDirRelPath:
4765      ClearErrors
4766
4767    FunctionEnd
4768
4769    !verbose pop
4770  !endif
4771!macroend
4772
4773!macro FindSMProgramsDirCall _REL_PATH_TO_DIR
4774  !verbose push
4775  !verbose ${_MOZFUNC_VERBOSE}
4776  Call FindSMProgramsDir
4777  Pop ${_REL_PATH_TO_DIR}
4778  !verbose pop
4779!macroend
4780
4781
4782################################################################################
4783# Macros for custom branding
4784
4785/**
4786 * Sets BrandFullName and / or BrandShortName to values provided in the specified
4787 * ini file and defaults to BrandShortName and BrandFullName as defined in
4788 * branding.nsi when the associated ini file entry is not specified.
4789 *
4790 * ini file format:
4791 * [Branding]
4792 * BrandFullName=Custom Full Name
4793 * BrandShortName=Custom Short Name
4794 *
4795 * @param   _PATH_TO_INI
4796 *          Path to the ini file.
4797 *
4798 * $R6 = return value from ReadINIStr
4799 * $R7 = stores BrandShortName
4800 * $R8 = stores BrandFullName
4801 * $R9 = _PATH_TO_INI
4802 */
4803!macro SetBrandNameVars
4804
4805  !ifndef ${_MOZFUNC_UN}SetBrandNameVars
4806    !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN}
4807    !insertmacro ${_MOZFUNC_UN_TMP}WordReplace
4808    !undef _MOZFUNC_UN
4809    !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP}
4810    !undef _MOZFUNC_UN_TMP
4811
4812    ; Prevent declaring vars twice when the SetBrandNameVars macro is
4813    ; inserted into both the installer and uninstaller.
4814    !ifndef SetBrandNameVars
4815      Var BrandFullName
4816      Var BrandFullNameDA
4817      Var BrandShortName
4818    !endif
4819
4820    !verbose push
4821    !verbose ${_MOZFUNC_VERBOSE}
4822    !define ${_MOZFUNC_UN}SetBrandNameVars "!insertmacro ${_MOZFUNC_UN}SetBrandNameVarsCall"
4823
4824    Function ${_MOZFUNC_UN}SetBrandNameVars
4825      Exch $R9
4826      Push $R8
4827      Push $R7
4828      Push $R6
4829
4830      StrCpy $R8 "${BrandFullName}"
4831      StrCpy $R7 "${BrandShortName}"
4832
4833      IfFileExists "$R9" +1 finish
4834
4835      ClearErrors
4836      ReadINIStr $R6 $R9 "Branding" "BrandFullName"
4837      IfErrors +2 +1
4838      StrCpy $R8 "$R6"
4839
4840      ClearErrors
4841      ReadINIStr $R6 $R9 "Branding" "BrandShortName"
4842      IfErrors +2 +1
4843      StrCpy $R7 "$R6"
4844
4845      finish:
4846      StrCpy $BrandFullName "$R8"
4847      ${${_MOZFUNC_UN}WordReplace} "$R8" "&" "&&" "+" $R8
4848      StrCpy $BrandFullNameDA "$R8"
4849      StrCpy $BrandShortName "$R7"
4850
4851      Pop $R6
4852      Pop $R7
4853      Pop $R8
4854      Exch $R9
4855    FunctionEnd
4856
4857    !verbose pop
4858  !endif
4859!macroend
4860
4861!macro SetBrandNameVarsCall _PATH_TO_INI
4862  !verbose push
4863  !verbose ${_MOZFUNC_VERBOSE}
4864  Push "${_PATH_TO_INI}"
4865  Call SetBrandNameVars
4866  !verbose pop
4867!macroend
4868
4869!macro un.SetBrandNameVarsCall _PATH_TO_INI
4870  !verbose push
4871  !verbose ${_MOZFUNC_VERBOSE}
4872  Push "${_PATH_TO_INI}"
4873  Call un.SetBrandNameVars
4874  !verbose pop
4875!macroend
4876
4877!macro un.SetBrandNameVars
4878  !ifndef un.SetBrandNameVars
4879    !verbose push
4880    !verbose ${_MOZFUNC_VERBOSE}
4881    !undef _MOZFUNC_UN
4882    !define _MOZFUNC_UN "un."
4883
4884    !insertmacro SetBrandNameVars
4885
4886    !undef _MOZFUNC_UN
4887    !define _MOZFUNC_UN
4888    !verbose pop
4889  !endif
4890!macroend
4891
4892/**
4893 * Replaces the wizard's header image with the one specified.
4894 *
4895 * @param   _PATH_TO_IMAGE
4896 *          Fully qualified path to the bitmap to use for the header image.
4897 *
4898 * $R8 = hwnd for the control returned from GetDlgItem.
4899 * $R9 = _PATH_TO_IMAGE
4900 */
4901!macro ChangeMUIHeaderImage
4902
4903  !ifndef ${_MOZFUNC_UN}ChangeMUIHeaderImage
4904    Var hHeaderBitmap
4905
4906    !verbose push
4907    !verbose ${_MOZFUNC_VERBOSE}
4908    !define ${_MOZFUNC_UN}ChangeMUIHeaderImage "!insertmacro ${_MOZFUNC_UN}ChangeMUIHeaderImageCall"
4909
4910    Function ${_MOZFUNC_UN}ChangeMUIHeaderImage
4911      Exch $R9
4912      Push $R8
4913
4914      GetDlgItem $R8 $HWNDPARENT 1046
4915      System::Call 'user32::LoadImageW(i 0, w "$R9", i 0, i 0, i 0, i 0x0010|0x2000) i.s'
4916      Pop $hHeaderBitmap
4917      SendMessage $R8 ${STM_SETIMAGE} 0 $hHeaderBitmap
4918      ; There is no way to specify a show function for a custom page so hide
4919      ; and then show the control to force the bitmap to redraw.
4920      ShowWindow $R8 ${SW_HIDE}
4921      ShowWindow $R8 ${SW_SHOW}
4922
4923      Pop $R8
4924      Exch $R9
4925    FunctionEnd
4926
4927    !verbose pop
4928  !endif
4929!macroend
4930
4931!macro ChangeMUIHeaderImageCall _PATH_TO_IMAGE
4932  !verbose push
4933  !verbose ${_MOZFUNC_VERBOSE}
4934  Push "${_PATH_TO_IMAGE}"
4935  Call ChangeMUIHeaderImage
4936  !verbose pop
4937!macroend
4938
4939!macro un.ChangeMUIHeaderImageCall _PATH_TO_IMAGE
4940  !verbose push
4941  !verbose ${_MOZFUNC_VERBOSE}
4942  Push "${_PATH_TO_IMAGE}"
4943  Call un.ChangeMUIHeaderImage
4944  !verbose pop
4945!macroend
4946
4947!macro un.ChangeMUIHeaderImage
4948  !ifndef un.ChangeMUIHeaderImage
4949    !verbose push
4950    !verbose ${_MOZFUNC_VERBOSE}
4951    !undef _MOZFUNC_UN
4952    !define _MOZFUNC_UN "un."
4953
4954    !insertmacro ChangeMUIHeaderImage
4955
4956    !undef _MOZFUNC_UN
4957    !define _MOZFUNC_UN
4958    !verbose pop
4959  !endif
4960!macroend
4961
4962
4963################################################################################
4964# User interface callback helper defines and macros
4965
4966/* Install type defines */
4967!ifndef INSTALLTYPE_BASIC
4968  !define INSTALLTYPE_BASIC     1
4969!endif
4970
4971!ifndef INSTALLTYPE_CUSTOM
4972  !define INSTALLTYPE_CUSTOM    2
4973!endif
4974
4975/**
4976 * Checks whether to display the current page (e.g. if not performing a custom
4977 * install don't display the custom pages).
4978 */
4979!macro CheckCustomCommon
4980
4981  !ifndef CheckCustomCommon
4982    !verbose push
4983    !verbose ${_MOZFUNC_VERBOSE}
4984    !define CheckCustomCommon "!insertmacro CheckCustomCommonCall"
4985
4986    Function CheckCustomCommon
4987
4988      ; Abort if not a custom install
4989      IntCmp $InstallType ${INSTALLTYPE_CUSTOM} +2 +1 +1
4990      Abort
4991
4992    FunctionEnd
4993
4994    !verbose pop
4995  !endif
4996!macroend
4997
4998!macro CheckCustomCommonCall
4999  !verbose push
5000  !verbose ${_MOZFUNC_VERBOSE}
5001  Call CheckCustomCommon
5002  !verbose pop
5003!macroend
5004
5005/**
5006 * Unloads dll's and releases references when the installer and uninstaller
5007 * exit.
5008 */
5009!macro OnEndCommon
5010
5011  !ifndef ${_MOZFUNC_UN}OnEndCommon
5012    !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN}
5013    !insertmacro ${_MOZFUNC_UN_TMP}UnloadUAC
5014    !undef _MOZFUNC_UN
5015    !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP}
5016    !undef _MOZFUNC_UN_TMP
5017
5018    !verbose push
5019    !verbose ${_MOZFUNC_VERBOSE}
5020    !define ${_MOZFUNC_UN}OnEndCommon "!insertmacro ${_MOZFUNC_UN}OnEndCommonCall"
5021
5022    Function ${_MOZFUNC_UN}OnEndCommon
5023
5024      ${${_MOZFUNC_UN}UnloadUAC}
5025      StrCmp $hHeaderBitmap "" +3 +1
5026      System::Call "gdi32::DeleteObject(i s)" $hHeaderBitmap
5027      StrCpy $hHeaderBitmap ""
5028
5029      System::Free 0
5030
5031    FunctionEnd
5032
5033    !verbose pop
5034  !endif
5035!macroend
5036
5037!macro OnEndCommonCall
5038  !verbose push
5039  !verbose ${_MOZFUNC_VERBOSE}
5040  Call OnEndCommon
5041  !verbose pop
5042!macroend
5043
5044!macro un.OnEndCommonCall
5045  !verbose push
5046  !verbose ${_MOZFUNC_VERBOSE}
5047  Call un.OnEndCommon
5048  !verbose pop
5049!macroend
5050
5051!macro un.OnEndCommon
5052  !ifndef un.OnEndCommon
5053    !verbose push
5054    !verbose ${_MOZFUNC_VERBOSE}
5055    !undef _MOZFUNC_UN
5056    !define _MOZFUNC_UN "un."
5057
5058    !insertmacro OnEndCommon
5059
5060    !undef _MOZFUNC_UN
5061    !define _MOZFUNC_UN
5062    !verbose pop
5063  !endif
5064!macroend
5065
5066/**
5067 * Called from the installer's .onInit function not to be confused with the
5068 * uninstaller's .onInit or the uninstaller's un.onInit functions.
5069 *
5070 * @param   _WARN_UNSUPPORTED_MSG
5071 *          Message displayed when the Windows version is not supported.
5072 *
5073 * $R5 = return value from the GetSize macro
5074 * $R6 = general string values, return value from GetTempFileName, return
5075 *       value from the GetSize macro
5076 * $R7 = full path to the configuration ini file
5077 * $R8 = used for OS Version and Service Pack detection and the return value
5078 *       from the GetParameters macro
5079 * $R9 = _WARN_UNSUPPORTED_MSG
5080 */
5081!macro InstallOnInitCommon
5082
5083  !ifndef InstallOnInitCommon
5084    !insertmacro ElevateUAC
5085    !insertmacro GetOptions
5086    !insertmacro GetParameters
5087    !insertmacro GetSize
5088
5089    !verbose push
5090    !verbose ${_MOZFUNC_VERBOSE}
5091    !define InstallOnInitCommon "!insertmacro InstallOnInitCommonCall"
5092
5093    Function InstallOnInitCommon
5094      Exch $R9
5095      Push $R8
5096      Push $R7
5097      Push $R6
5098      Push $R5
5099
5100      ; Don't install on systems that don't support SSE2. The parameter value of
5101      ; 10 is for PF_XMMI64_INSTRUCTIONS_AVAILABLE which will check whether the
5102      ; SSE2 instruction set is available.
5103      System::Call "kernel32::IsProcessorFeaturePresent(i 10)i .R8"
5104      ${If} "$R8" == "0"
5105        MessageBox MB_OK|MB_ICONSTOP "$R9"
5106        ; Nothing initialized so no need to call OnEndCommon
5107        Quit
5108      ${EndIf}
5109
5110      !ifdef HAVE_64BIT_BUILD
5111        ${Unless} ${RunningX64}
5112        ${OrUnless} ${AtLeastWin7}
5113          MessageBox MB_OK|MB_ICONSTOP "$R9"
5114          ; Nothing initialized so no need to call OnEndCommon
5115          Quit
5116        ${EndUnless}
5117
5118        SetRegView 64
5119      !else
5120        StrCpy $R8 "0"
5121        ${If} ${AtMostWin2000}
5122          StrCpy $R8 "1"
5123        ${EndIf}
5124
5125        ${If} ${IsWinXP}
5126        ${AndIf} ${AtMostServicePack} 1
5127          StrCpy $R8 "1"
5128        ${EndIf}
5129
5130        ${If} $R8 == "1"
5131          ; XXX-rstrong - some systems failed the AtLeastWin2000 test that we
5132          ; used to use for an unknown reason and likely fail the AtMostWin2000
5133          ; and possibly the IsWinXP test as well. To work around this also
5134          ; check if the Windows NT registry Key exists and if it does if the
5135          ; first char in CurrentVersion is equal to 3 (Windows NT 3.5 and
5136          ; 3.5.1), to 4 (Windows NT 4) or 5 (Windows 2000 and Windows XP).
5137          StrCpy $R8 ""
5138          ClearErrors
5139          ReadRegStr $R8 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" "CurrentVersion"
5140          StrCpy $R8 "$R8" 1
5141          ${If} ${Errors}
5142          ${OrIf} "$R8" == "3"
5143          ${OrIf} "$R8" == "4"
5144          ${OrIf} "$R8" == "5"
5145            MessageBox MB_OK|MB_ICONSTOP "$R9"
5146            ; Nothing initialized so no need to call OnEndCommon
5147            Quit
5148          ${EndIf}
5149        ${EndUnless}
5150      !endif
5151
5152      ${GetParameters} $R8
5153
5154      ${If} $R8 != ""
5155        ; Default install type
5156        StrCpy $InstallType ${INSTALLTYPE_BASIC}
5157
5158        ${Unless} ${Silent}
5159          ; Manually check for /S in the command line due to Bug 506867
5160          ClearErrors
5161          ${GetOptions} "$R8" "/S" $R7
5162          ${Unless} ${Errors}
5163            SetSilent silent
5164          ${Else}
5165            ; Support for the deprecated -ms command line argument. The new command
5166            ; line arguments are not supported when -ms is used.
5167            ClearErrors
5168            ${GetOptions} "$R8" "-ms" $R7
5169            ${Unless} ${Errors}
5170              SetSilent silent
5171            ${EndUnless}
5172          ${EndUnless}
5173        ${EndUnless}
5174
5175        ; Support for specifying an installation configuration file.
5176        ClearErrors
5177        ${GetOptions} "$R8" "/INI=" $R7
5178        ${Unless} ${Errors}
5179          ; The configuration file must also exist
5180          ${If} ${FileExists} "$R7"
5181            SetSilent silent
5182            ReadINIStr $R8 $R7 "Install" "InstallDirectoryName"
5183            ${If} $R8 != ""
5184              !ifdef HAVE_64BIT_BUILD
5185                StrCpy $INSTDIR "$PROGRAMFILES64\$R8"
5186              !else
5187                StrCpy $INSTDIR "$PROGRAMFILES32\$R8"
5188              !endif
5189            ${Else}
5190              ReadINIStr $R8 $R7 "Install" "InstallDirectoryPath"
5191              ${If} $R8 != ""
5192                StrCpy $INSTDIR "$R8"
5193              ${EndIf}
5194            ${EndIf}
5195
5196            ; Quit if we are unable to create the installation directory or we are
5197            ; unable to write to a file in the installation directory.
5198            ClearErrors
5199            ${If} ${FileExists} "$INSTDIR"
5200              GetTempFileName $R6 "$INSTDIR"
5201              FileOpen $R5 "$R6" w
5202              FileWrite $R5 "Write Access Test"
5203              FileClose $R5
5204              Delete $R6
5205              ${If} ${Errors}
5206                ; Attempt to elevate and then try again.
5207                ${ElevateUAC}
5208                GetTempFileName $R6 "$INSTDIR"
5209                FileOpen $R5 "$R6" w
5210                FileWrite $R5 "Write Access Test"
5211                FileClose $R5
5212                Delete $R6
5213                ${If} ${Errors}
5214                  ; Nothing initialized so no need to call OnEndCommon
5215                  Quit
5216                ${EndIf}
5217              ${EndIf}
5218            ${Else}
5219              CreateDirectory "$INSTDIR"
5220              ${If} ${Errors}
5221                ; Attempt to elevate and then try again.
5222                ${ElevateUAC}
5223                CreateDirectory "$INSTDIR"
5224                ${If} ${Errors}
5225                  ; Nothing initialized so no need to call OnEndCommon
5226                  Quit
5227                ${EndIf}
5228              ${EndIf}
5229            ${EndIf}
5230
5231            ReadINIStr $R8 $R7 "Install" "QuickLaunchShortcut"
5232            ${If} $R8 == "false"
5233              StrCpy $AddQuickLaunchSC "0"
5234            ${Else}
5235              StrCpy $AddQuickLaunchSC "1"
5236            ${EndIf}
5237
5238            ReadINIStr $R8 $R7 "Install" "DesktopShortcut"
5239            ${If} $R8 == "false"
5240              StrCpy $AddDesktopSC "0"
5241            ${Else}
5242              StrCpy $AddDesktopSC "1"
5243            ${EndIf}
5244
5245            ReadINIStr $R8 $R7 "Install" "StartMenuShortcuts"
5246            ${If} $R8 == "false"
5247              StrCpy $AddStartMenuSC "0"
5248            ${Else}
5249              StrCpy $AddStartMenuSC "1"
5250            ${EndIf}
5251
5252            ReadINIStr $R8 $R7 "Install" "TaskbarShortcut"
5253            ${If} $R8 == "false"
5254              StrCpy $AddTaskbarSC "0"
5255            ${Else}
5256              StrCpy $AddTaskbarSC "1"
5257            ${EndIf}
5258
5259            ReadINIStr $R8 $R7 "Install" "MaintenanceService"
5260            ${If} $R8 == "false"
5261              StrCpy $InstallMaintenanceService "0"
5262            ${Else}
5263              ; Installing the service always requires elevation.
5264              ${ElevateUAC}
5265            ${EndIf}
5266
5267            !ifndef NO_STARTMENU_DIR
5268              ReadINIStr $R8 $R7 "Install" "StartMenuDirectoryName"
5269              ${If} $R8 != ""
5270                StrCpy $StartMenuDir "$R8"
5271              ${EndIf}
5272            !endif
5273          ${EndIf}
5274        ${Else}
5275          ; If this isn't an INI install, we need to try to elevate now.
5276          ; We'll check the user's permission level later on to determine the
5277          ; default install path (which will be the real install path for /S).
5278          ; If an INI file is used, we try to elevate down that path when needed.
5279          ${ElevateUAC}
5280        ${EndUnless}
5281      ${EndIf}
5282      ClearErrors
5283
5284      ${IfNot} ${Silent}
5285        ${ElevateUAC}
5286      ${EndIf}
5287
5288      Pop $R5
5289      Pop $R6
5290      Pop $R7
5291      Pop $R8
5292      Exch $R9
5293    FunctionEnd
5294
5295    !verbose pop
5296  !endif
5297!macroend
5298
5299!macro InstallOnInitCommonCall _WARN_UNSUPPORTED_MSG
5300  !verbose push
5301  !verbose ${_MOZFUNC_VERBOSE}
5302  Push "${_WARN_UNSUPPORTED_MSG}"
5303  Call InstallOnInitCommon
5304  !verbose pop
5305!macroend
5306
5307/**
5308 * Called from the uninstaller's .onInit function not to be confused with the
5309 * installer's .onInit or the uninstaller's un.onInit functions.
5310 */
5311!macro UninstallOnInitCommon
5312
5313  !ifndef UninstallOnInitCommon
5314    !insertmacro ElevateUAC
5315    !insertmacro GetLongPath
5316    !insertmacro GetOptions
5317    !insertmacro GetParameters
5318    !insertmacro GetParent
5319    !insertmacro UnloadUAC
5320    !insertmacro UpdateShortcutAppModelIDs
5321    !insertmacro UpdateUninstallLog
5322
5323    !verbose push
5324    !verbose ${_MOZFUNC_VERBOSE}
5325    !define UninstallOnInitCommon "!insertmacro UninstallOnInitCommonCall"
5326
5327    Function UninstallOnInitCommon
5328      ; Prevents breaking apps that don't use SetBrandNameVars
5329      !ifdef SetBrandNameVars
5330        ${SetBrandNameVars} "$EXEDIR\distribution\setup.ini"
5331      !endif
5332
5333      ; Prevent launching the application when a reboot is required and this
5334      ; executable is the main application executable
5335      IfFileExists "$EXEDIR\${FileMainEXE}.moz-upgrade" +1 +4
5336      MessageBox MB_YESNO|MB_ICONEXCLAMATION "$(WARN_RESTART_REQUIRED_UPGRADE)" IDNO +2
5337      Reboot
5338      Quit ; Nothing initialized so no need to call OnEndCommon
5339
5340      ${GetParent} "$EXEDIR" $INSTDIR
5341      ${GetLongPath} "$INSTDIR" $INSTDIR
5342      IfFileExists "$INSTDIR\${FileMainEXE}" +2 +1
5343      Quit ; Nothing initialized so no need to call OnEndCommon
5344
5345!ifmacrodef InitHashAppModelId
5346      ; setup the application model id registration value
5347      !ifdef AppName
5348      ${InitHashAppModelId} "$INSTDIR" "Software\Mozilla\${AppName}\TaskBarIDs"
5349      !endif
5350!endif
5351
5352      ; Prevents breaking apps that don't use SetBrandNameVars
5353      !ifdef SetBrandNameVars
5354        ${SetBrandNameVars} "$INSTDIR\distribution\setup.ini"
5355      !endif
5356
5357      ; Application update uses a directory named tobedeleted in the $INSTDIR to
5358      ; delete files on OS reboot when they are in use. Try to delete this
5359      ; directory if it exists.
5360      ${If} ${FileExists} "$INSTDIR\${TO_BE_DELETED}"
5361        RmDir /r "$INSTDIR\${TO_BE_DELETED}"
5362      ${EndIf}
5363
5364      ; Prevent all operations (e.g. set as default, postupdate, etc.) when a
5365      ; reboot is required and the executable launched is helper.exe
5366      IfFileExists "$INSTDIR\${FileMainEXE}.moz-upgrade" +1 +4
5367      MessageBox MB_YESNO|MB_ICONEXCLAMATION "$(WARN_RESTART_REQUIRED_UPGRADE)" IDNO +2
5368      Reboot
5369      Quit ; Nothing initialized so no need to call OnEndCommon
5370
5371      !ifdef HAVE_64BIT_BUILD
5372        SetRegView 64
5373      !endif
5374
5375      ${GetParameters} $R0
5376
5377      StrCmp "$R0" "" continue +1
5378
5379      ; Update this user's shortcuts with the latest app user model id.
5380      ClearErrors
5381      ${GetOptions} "$R0" "/UpdateShortcutAppUserModelIds" $R2
5382      IfErrors hideshortcuts +1
5383      StrCpy $R2 ""
5384!ifmacrodef InitHashAppModelId
5385      ${If} "$AppUserModelID" != ""
5386        ${UpdateShortcutAppModelIDs}  "$INSTDIR\${FileMainEXE}" "$AppUserModelID" $R2
5387      ${EndIf}
5388!endif
5389      StrCmp "$R2" "false" +1 finish ; true indicates that shortcuts have been updated
5390      Quit ; Nothing initialized so no need to call OnEndCommon
5391
5392      ; Require elevation if the user can elevate
5393      hideshortcuts:
5394      ClearErrors
5395      ${GetOptions} "$R0" "/HideShortcuts" $R2
5396      IfErrors showshortcuts +1
5397!ifndef NONADMIN_ELEVATE
5398      ${ElevateUAC}
5399!endif
5400      ${HideShortcuts}
5401      GoTo finish
5402
5403      ; Require elevation if the user can elevate
5404      showshortcuts:
5405      ClearErrors
5406      ${GetOptions} "$R0" "/ShowShortcuts" $R2
5407      IfErrors defaultappuser +1
5408!ifndef NONADMIN_ELEVATE
5409      ${ElevateUAC}
5410!endif
5411      ${ShowShortcuts}
5412      GoTo finish
5413
5414      ; Require elevation if the the StartMenuInternet registry keys require
5415      ; updating and the user can elevate
5416      defaultappuser:
5417      ClearErrors
5418      ${GetOptions} "$R0" "/SetAsDefaultAppUser" $R2
5419      IfErrors defaultappglobal +1
5420      ${SetAsDefaultAppUser}
5421      GoTo finish
5422
5423      ; Require elevation if the user can elevate
5424      defaultappglobal:
5425      ClearErrors
5426      ${GetOptions} "$R0" "/SetAsDefaultAppGlobal" $R2
5427      IfErrors postupdate +1
5428      ${ElevateUAC}
5429      ${SetAsDefaultAppGlobal}
5430      GoTo finish
5431
5432      ; Do not attempt to elevate. The application launching this executable is
5433      ; responsible for elevation if it is required.
5434      postupdate:
5435      ${WordReplace} "$R0" "$\"" "" "+" $R0
5436      ClearErrors
5437      ${GetOptions} "$R0" "/PostUpdate" $R2
5438      IfErrors continue +1
5439      ; If the uninstall.log does not exist don't perform post update
5440      ; operations. This prevents updating the registry for zip builds.
5441      IfFileExists "$EXEDIR\uninstall.log" +2 +1
5442      Quit ; Nothing initialized so no need to call OnEndCommon
5443      ${PostUpdate}
5444      ClearErrors
5445      ${GetOptions} "$R0" "/UninstallLog=" $R2
5446      IfErrors updateuninstalllog +1
5447      StrCmp "$R2" "" finish +1
5448      GetFullPathName $R3 "$R2"
5449      IfFileExists "$R3" +1 finish
5450      Delete "$INSTDIR\uninstall\*wizard*"
5451      Delete "$INSTDIR\uninstall\uninstall.log"
5452      CopyFiles /SILENT /FILESONLY "$R3" "$INSTDIR\uninstall\"
5453      ${GetParent} "$R3" $R4
5454      Delete "$R3"
5455      RmDir "$R4"
5456      GoTo finish
5457
5458      ; Do not attempt to elevate. The application launching this executable is
5459      ; responsible for elevation if it is required.
5460      updateuninstalllog:
5461      ${UpdateUninstallLog}
5462
5463      finish:
5464      ${UnloadUAC}
5465      System::Call "shell32::SHChangeNotify(i ${SHCNE_ASSOCCHANGED}, i 0, i 0, i 0)"
5466      Quit ; Nothing initialized so no need to call OnEndCommon
5467
5468      continue:
5469
5470      ; If the uninstall.log does not exist don't perform uninstall
5471      ; operations. This prevents running the uninstaller for zip builds.
5472      IfFileExists "$INSTDIR\uninstall\uninstall.log" +2 +1
5473      Quit ; Nothing initialized so no need to call OnEndCommon
5474
5475      ; Require elevation if the user can elevate
5476      ${ElevateUAC}
5477
5478      ; If we made it this far then this installer is being used as an uninstaller.
5479      WriteUninstaller "$EXEDIR\uninstaller.exe"
5480
5481      ${Unless} ${Silent}
5482        ; Manually check for /S in the command line due to Bug 506867
5483        ClearErrors
5484        ${GetOptions} "$R0" "/S" $R2
5485        ${Unless} ${Errors}
5486          SetSilent silent
5487        ${Else}
5488          ; Support for the deprecated -ms command line argument.
5489          ClearErrors
5490          ${GetOptions} "$R0" "-ms" $R2
5491          ${Unless} ${Errors}
5492            SetSilent silent
5493          ${EndUnless}
5494        ${EndUnless}
5495      ${EndUnless}
5496
5497      ${If} ${Silent}
5498        StrCpy $R1 "$\"$EXEDIR\uninstaller.exe$\" /S"
5499      ${Else}
5500        StrCpy $R1 "$\"$EXEDIR\uninstaller.exe$\""
5501      ${EndIf}
5502
5503      ; When the uninstaller is launched it copies itself to the temp directory
5504      ; so it won't be in use so it can delete itself.
5505      ExecWait $R1
5506      ${DeleteFile} "$EXEDIR\uninstaller.exe"
5507      ${UnloadUAC}
5508      SetErrorLevel 0
5509      Quit ; Nothing initialized so no need to call OnEndCommon
5510
5511    FunctionEnd
5512
5513    !verbose pop
5514  !endif
5515!macroend
5516
5517!macro UninstallOnInitCommonCall
5518  !verbose push
5519  !verbose ${_MOZFUNC_VERBOSE}
5520  Call UninstallOnInitCommon
5521  !verbose pop
5522!macroend
5523
5524/**
5525 * Called from the uninstaller's un.onInit function not to be confused with the
5526 * installer's .onInit or the uninstaller's .onInit functions.
5527 */
5528!macro un.UninstallUnOnInitCommon
5529
5530  !ifndef un.UninstallUnOnInitCommon
5531    !insertmacro un.GetLongPath
5532    !insertmacro un.GetParent
5533    !insertmacro un.SetBrandNameVars
5534
5535    !verbose push
5536    !verbose ${_MOZFUNC_VERBOSE}
5537    !define un.UninstallUnOnInitCommon "!insertmacro un.UninstallUnOnInitCommonCall"
5538
5539    Function un.UninstallUnOnInitCommon
5540      ${un.GetParent} "$INSTDIR" $INSTDIR
5541      ${un.GetLongPath} "$INSTDIR" $INSTDIR
5542      ${Unless} ${FileExists} "$INSTDIR\${FileMainEXE}"
5543        Abort
5544      ${EndUnless}
5545
5546      !ifdef HAVE_64BIT_BUILD
5547        SetRegView 64
5548      !endif
5549
5550      ; Prevents breaking apps that don't use SetBrandNameVars
5551      !ifdef un.SetBrandNameVars
5552        ${un.SetBrandNameVars} "$INSTDIR\distribution\setup.ini"
5553      !endif
5554
5555      ; Initialize $hHeaderBitmap to prevent redundant changing of the bitmap if
5556      ; the user clicks the back button
5557      StrCpy $hHeaderBitmap ""
5558    FunctionEnd
5559
5560    !verbose pop
5561  !endif
5562!macroend
5563
5564!macro un.UninstallUnOnInitCommonCall
5565  !verbose push
5566  !verbose ${_MOZFUNC_VERBOSE}
5567  Call un.UninstallUnOnInitCommon
5568  !verbose pop
5569!macroend
5570
5571/**
5572 * Called from the MUI leaveOptions function to set the value of $INSTDIR.
5573 */
5574!macro LeaveOptionsCommon
5575
5576  !ifndef LeaveOptionsCommon
5577    !insertmacro CanWriteToInstallDir
5578    !insertmacro GetLongPath
5579
5580!ifndef NO_INSTDIR_FROM_REG
5581    !insertmacro GetSingleInstallPath
5582!endif
5583
5584    !verbose push
5585    !verbose ${_MOZFUNC_VERBOSE}
5586    !define LeaveOptionsCommon "!insertmacro LeaveOptionsCommonCall"
5587
5588    Function LeaveOptionsCommon
5589      Push $R9
5590
5591!ifndef NO_INSTDIR_FROM_REG
5592      SetShellVarContext all      ; Set SHCTX to HKLM
5593      ${GetSingleInstallPath} "Software\Mozilla\${BrandFullNameInternal}" $R9
5594
5595      StrCmp "$R9" "false" +1 finish_get_install_dir
5596
5597      SetShellVarContext current  ; Set SHCTX to HKCU
5598      ${GetSingleInstallPath} "Software\Mozilla\${BrandFullNameInternal}" $R9
5599
5600      ${If} ${RunningX64}
5601        ; In HKCU there is no WOW64 redirection, which means we may have gotten
5602        ; the path to a 32-bit install even though we're 64-bit, or vice-versa.
5603        ; In that case, just use the default path instead of offering an upgrade.
5604        ; But only do that override if the existing install is in Program Files,
5605        ; because that's the only place we can be sure is specific
5606        ; to either 32 or 64 bit applications.
5607        ; The WordFind syntax below searches for the first occurence of the
5608        ; "delimiter" (the Program Files path) in the install path and returns
5609        ; anything that appears before that. If nothing appears before that,
5610        ; then the install is under Program Files (32 or 64).
5611!ifdef HAVE_64BIT_BUILD
5612        ${WordFind} $R9 $PROGRAMFILES32 "+1{" $0
5613!else
5614        ${WordFind} $R9 $PROGRAMFILES64 "+1{" $0
5615!endif
5616        ${If} $0 == ""
5617          StrCpy $R9 "false"
5618        ${EndIf}
5619      ${EndIf}
5620
5621      finish_get_install_dir:
5622      StrCmp "$R9" "false" +2 +1
5623      StrCpy $INSTDIR "$R9"
5624!endif
5625
5626      ; If the user doesn't have write access to the installation directory set
5627      ; the installation directory to a subdirectory of the All Users application
5628      ; directory and if the user can't write to that location set the installation
5629      ; directory to a subdirectory of the users local application directory
5630      ; (e.g. non-roaming).
5631      ${CanWriteToInstallDir} $R9
5632      StrCmp "$R9" "false" +1 finish_check_install_dir
5633
5634      SetShellVarContext all      ; Set SHCTX to All Users
5635      StrCpy $INSTDIR "$APPDATA\${BrandFullName}\"
5636      ${CanWriteToInstallDir} $R9
5637      StrCmp "$R9" "false" +2 +1
5638      StrCpy $INSTDIR "$LOCALAPPDATA\${BrandFullName}\"
5639
5640      finish_check_install_dir:
5641      IfFileExists "$INSTDIR" +3 +1
5642      Pop $R9
5643      Return
5644
5645      ; Always display the long path if the path already exists.
5646      ${GetLongPath} "$INSTDIR" $INSTDIR
5647
5648      ; The call to GetLongPath returns a long path without a trailing
5649      ; back-slash. Append a \ to the path to prevent the directory
5650      ; name from being appended when using the NSIS create new folder.
5651      ; http://www.nullsoft.com/free/nsis/makensis.htm#InstallDir
5652      StrCpy $INSTDIR "$INSTDIR\"
5653
5654      Pop $R9
5655    FunctionEnd
5656
5657    !verbose pop
5658  !endif
5659!macroend
5660
5661!macro LeaveOptionsCommonCall
5662  !verbose push
5663  !verbose ${_MOZFUNC_VERBOSE}
5664  Call LeaveOptionsCommon
5665  !verbose pop
5666!macroend
5667
5668/**
5669 * Called from the MUI preDirectory function to verify there is enough disk
5670 * space for the installation and the installation directory is writable.
5671 *
5672 * $R9 = returned value from CheckDiskSpace and CanWriteToInstallDir macros
5673 */
5674!macro PreDirectoryCommon
5675
5676  !ifndef PreDirectoryCommon
5677    !insertmacro CanWriteToInstallDir
5678    !insertmacro CheckDiskSpace
5679
5680    !verbose push
5681    !verbose ${_MOZFUNC_VERBOSE}
5682    !define PreDirectoryCommon "!insertmacro PreDirectoryCommonCall"
5683
5684    Function PreDirectoryCommon
5685      Push $R9
5686
5687      IntCmp $InstallType ${INSTALLTYPE_CUSTOM} end +1 +1
5688      ${CanWriteToInstallDir} $R9
5689      StrCmp "$R9" "false" end +1
5690      ${CheckDiskSpace} $R9
5691      StrCmp "$R9" "false" end +1
5692      Abort
5693
5694      end:
5695
5696      Pop $R9
5697    FunctionEnd
5698
5699    !verbose pop
5700  !endif
5701!macroend
5702
5703!macro PreDirectoryCommonCall
5704  !verbose push
5705  !verbose ${_MOZFUNC_VERBOSE}
5706  Call PreDirectoryCommon
5707  !verbose pop
5708!macroend
5709
5710/**
5711 * Called from the MUI leaveDirectory function
5712 *
5713 * @param   _WARN_DISK_SPACE
5714 *          Message displayed when there isn't enough disk space to perform the
5715 *          installation.
5716 * @param   _WARN_WRITE_ACCESS
5717 *          Message displayed when the installer does not have write access to
5718 *          $INSTDIR.
5719 *
5720 * $R7 = returned value from CheckDiskSpace and CanWriteToInstallDir macros
5721 * $R8 = _WARN_DISK_SPACE
5722 * $R9 = _WARN_WRITE_ACCESS
5723 */
5724!macro LeaveDirectoryCommon
5725
5726  !ifndef LeaveDirectoryCommon
5727    !insertmacro CheckDiskSpace
5728    !insertmacro CanWriteToInstallDir
5729
5730    !verbose push
5731    !verbose ${_MOZFUNC_VERBOSE}
5732    !define LeaveDirectoryCommon "!insertmacro LeaveDirectoryCommonCall"
5733
5734    Function LeaveDirectoryCommon
5735      Exch $R9
5736      Exch 1
5737      Exch $R8
5738      Push $R7
5739
5740      ${CanWriteToInstallDir} $R7
5741      ${If} $R7 == "false"
5742        MessageBox MB_OK|MB_ICONEXCLAMATION "$R9"
5743        Abort
5744      ${EndIf}
5745
5746      ${CheckDiskSpace} $R7
5747      ${If} $R7 == "false"
5748        MessageBox MB_OK|MB_ICONEXCLAMATION "$R8"
5749        Abort
5750      ${EndIf}
5751
5752      Pop $R7
5753      Exch $R8
5754      Exch 1
5755      Exch $R9
5756    FunctionEnd
5757
5758    !verbose pop
5759  !endif
5760!macroend
5761
5762!macro LeaveDirectoryCommonCall _WARN_DISK_SPACE _WARN_WRITE_ACCESS
5763  !verbose push
5764  Push "${_WARN_DISK_SPACE}"
5765  Push "${_WARN_WRITE_ACCESS}"
5766  !verbose ${_MOZFUNC_VERBOSE}
5767  Call LeaveDirectoryCommon
5768  !verbose pop
5769!macroend
5770
5771
5772################################################################################
5773# Install Section common macros.
5774
5775/**
5776 * Performs common cleanup operations prior to the actual installation.
5777 * This macro should be called first when installation starts.
5778 */
5779!macro InstallStartCleanupCommon
5780
5781  !ifndef InstallStartCleanupCommon
5782    !insertmacro CleanVirtualStore
5783    !insertmacro EndUninstallLog
5784    !insertmacro OnInstallUninstall
5785
5786    !verbose push
5787    !verbose ${_MOZFUNC_VERBOSE}
5788    !define InstallStartCleanupCommon "!insertmacro InstallStartCleanupCommonCall"
5789
5790    Function InstallStartCleanupCommon
5791
5792      ; Remove files not removed by parsing the uninstall.log
5793      Delete "$INSTDIR\install_wizard.log"
5794      Delete "$INSTDIR\install_status.log"
5795
5796      RmDir /r "$INSTDIR\updates"
5797      Delete "$INSTDIR\updates.xml"
5798      Delete "$INSTDIR\active-update.xml"
5799
5800      ; Remove files from the uninstall directory.
5801      ${If} ${FileExists} "$INSTDIR\uninstall"
5802        Delete "$INSTDIR\uninstall\*wizard*"
5803        Delete "$INSTDIR\uninstall\uninstall.ini"
5804        Delete "$INSTDIR\uninstall\cleanup.log"
5805        Delete "$INSTDIR\uninstall\uninstall.update"
5806        ${OnInstallUninstall}
5807      ${EndIf}
5808
5809      ; Since we write to the uninstall.log in this directory during the
5810      ; installation create the directory if it doesn't already exist.
5811      IfFileExists "$INSTDIR\uninstall" +2 +1
5812      CreateDirectory "$INSTDIR\uninstall"
5813
5814      ; Application update uses a directory named tobedeleted in the $INSTDIR to
5815      ; delete files on OS reboot when they are in use. Try to delete this
5816      ; directory if it exists.
5817      ${If} ${FileExists} "$INSTDIR\${TO_BE_DELETED}"
5818        RmDir /r "$INSTDIR\${TO_BE_DELETED}"
5819      ${EndIf}
5820
5821      ; Remove files that may be left behind by the application in the
5822      ; VirtualStore directory.
5823      ${CleanVirtualStore}
5824    FunctionEnd
5825
5826    !verbose pop
5827  !endif
5828!macroend
5829
5830!macro InstallStartCleanupCommonCall
5831  !verbose push
5832  !verbose ${_MOZFUNC_VERBOSE}
5833  Call InstallStartCleanupCommon
5834  !verbose pop
5835!macroend
5836
5837/**
5838 * Performs common cleanup operations after the actual installation.
5839 * This macro should be called last during the installation.
5840 */
5841!macro InstallEndCleanupCommon
5842
5843  !ifndef InstallEndCleanupCommon
5844    !insertmacro EndUninstallLog
5845
5846    !verbose push
5847    !verbose ${_MOZFUNC_VERBOSE}
5848    !define InstallEndCleanupCommon "!insertmacro InstallEndCleanupCommonCall"
5849
5850    Function InstallEndCleanupCommon
5851
5852      ; Close the file handle to the uninstall.log
5853      ${EndUninstallLog}
5854
5855    FunctionEnd
5856
5857    !verbose pop
5858  !endif
5859!macroend
5860
5861!macro InstallEndCleanupCommonCall
5862  !verbose push
5863  !verbose ${_MOZFUNC_VERBOSE}
5864  Call InstallEndCleanupCommon
5865  !verbose pop
5866!macroend
5867
5868
5869################################################################################
5870# UAC Related Macros
5871
5872/**
5873 * Provides UAC elevation support for Vista and above (requires the UAC plugin).
5874 *
5875 * $0 = return values from calls to the UAC plugin (always uses $0)
5876 * $R9 = return values from GetParameters and GetOptions macros
5877 */
5878!macro ElevateUAC
5879
5880  !ifndef ${_MOZFUNC_UN}ElevateUAC
5881    !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN}
5882    !insertmacro ${_MOZFUNC_UN_TMP}GetOptions
5883    !insertmacro ${_MOZFUNC_UN_TMP}GetParameters
5884    !undef _MOZFUNC_UN
5885    !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP}
5886    !undef _MOZFUNC_UN_TMP
5887
5888    !verbose push
5889    !verbose ${_MOZFUNC_VERBOSE}
5890    !define ${_MOZFUNC_UN}ElevateUAC "!insertmacro ${_MOZFUNC_UN}ElevateUACCall"
5891
5892    Function ${_MOZFUNC_UN}ElevateUAC
5893      Push $R9
5894      Push $0
5895
5896!ifndef NONADMIN_ELEVATE
5897        ${If} ${AtLeastWinVista}
5898          UAC::IsAdmin
5899          ; If the user is not an admin already
5900          ${If} "$0" != "1"
5901            UAC::SupportsUAC
5902            ; If the system supports UAC
5903            ${If} "$0" == "1"
5904              UAC::GetElevationType
5905              ; If the user account has a split token
5906              ${If} "$0" == "3"
5907                UAC::RunElevated
5908                UAC::Unload
5909                ; Nothing besides UAC initialized so no need to call OnEndCommon
5910                Quit
5911              ${EndIf}
5912            ${EndIf}
5913          ${Else}
5914            ${GetParameters} $R9
5915            ${If} $R9 != ""
5916              ClearErrors
5917              ${GetOptions} "$R9" "/UAC:" $0
5918              ; If the command line contains /UAC then we need to initialize
5919              ; the UAC plugin to use UAC::ExecCodeSegment to execute code in
5920              ; the non-elevated context.
5921              ${Unless} ${Errors}
5922                UAC::RunElevated
5923              ${EndUnless}
5924            ${EndIf}
5925          ${EndIf}
5926        ${EndIf}
5927!else
5928      ${If} ${AtLeastWinVista}
5929        UAC::IsAdmin
5930        ; If the user is not an admin already
5931        ${If} "$0" != "1"
5932          UAC::SupportsUAC
5933          ; If the system supports UAC require that the user elevate
5934          ${If} "$0" == "1"
5935            UAC::GetElevationType
5936            ; If the user account has a split token
5937            ${If} "$0" == "3"
5938              UAC::RunElevated
5939              UAC::Unload
5940              ; Nothing besides UAC initialized so no need to call OnEndCommon
5941              Quit
5942            ${EndIf}
5943          ${Else}
5944            ; Check if UAC is enabled. If the user has turned UAC on or off
5945            ; without rebooting this value will be incorrect. This is an
5946            ; edgecase that we have to live with when trying to allow
5947            ; installing when the user doesn't have privileges such as a public
5948            ; computer while trying to also achieve UAC elevation. When this
5949            ; happens the user will be presented with the runas dialog if the
5950            ; value is 1 and won't be presented with the UAC dialog when the
5951            ; value is 0.
5952            ReadRegDWord $R9 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" "EnableLUA"
5953            ${If} "$R9" == "1"
5954              ; This will display the UAC version of the runas dialog which
5955              ; requires a password for an existing user account.
5956              UAC::RunElevated
5957              ${If} "$0" == "0" ; Was elevation successful
5958                UAC::Unload
5959                ; Nothing besides UAC initialized so no need to call OnEndCommon
5960                Quit
5961              ${EndIf}
5962              ; Unload UAC since the elevation request was not successful and
5963              ; install anyway.
5964              UAC::Unload
5965            ${EndIf}
5966          ${EndIf}
5967        ${Else}
5968          ClearErrors
5969          ${${_MOZFUNC_UN}GetParameters} $R9
5970          ${${_MOZFUNC_UN}GetOptions} "$R9" "/UAC:" $R9
5971          ; If the command line contains /UAC then we need to initialize the UAC
5972          ; plugin to use UAC::ExecCodeSegment to execute code in the
5973          ; non-elevated context.
5974          ${Unless} ${Errors}
5975            UAC::RunElevated
5976          ${EndUnless}
5977        ${EndIf}
5978      ${EndIf}
5979!endif
5980
5981      ClearErrors
5982
5983      Pop $0
5984      Pop $R9
5985    FunctionEnd
5986
5987    !verbose pop
5988  !endif
5989!macroend
5990
5991!macro ElevateUACCall
5992  !verbose push
5993  !verbose ${_MOZFUNC_VERBOSE}
5994  Call ElevateUAC
5995  !verbose pop
5996!macroend
5997
5998!macro un.ElevateUACCall
5999  !verbose push
6000  !verbose ${_MOZFUNC_VERBOSE}
6001  Call un.ElevateUAC
6002  !verbose pop
6003!macroend
6004
6005!macro un.ElevateUAC
6006  !ifndef un.ElevateUAC
6007    !verbose push
6008    !verbose ${_MOZFUNC_VERBOSE}
6009    !undef _MOZFUNC_UN
6010    !define _MOZFUNC_UN "un."
6011
6012    !insertmacro ElevateUAC
6013
6014    !undef _MOZFUNC_UN
6015    !define _MOZFUNC_UN
6016    !verbose pop
6017  !endif
6018!macroend
6019
6020/**
6021 * Unloads the UAC plugin so the NSIS plugins can be removed when the installer
6022 * and uninstaller exit.
6023 *
6024 * $R9 = return values from GetParameters and GetOptions macros
6025 */
6026!macro UnloadUAC
6027
6028  !ifndef ${_MOZFUNC_UN}UnloadUAC
6029    !define _MOZFUNC_UN_TMP_UnloadUAC ${_MOZFUNC_UN}
6030    !insertmacro ${_MOZFUNC_UN_TMP_UnloadUAC}GetOptions
6031    !insertmacro ${_MOZFUNC_UN_TMP_UnloadUAC}GetParameters
6032    !undef _MOZFUNC_UN
6033    !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP_UnloadUAC}
6034    !undef _MOZFUNC_UN_TMP_UnloadUAC
6035
6036    !verbose push
6037    !verbose ${_MOZFUNC_VERBOSE}
6038    !define ${_MOZFUNC_UN}UnloadUAC "!insertmacro ${_MOZFUNC_UN}UnloadUACCall"
6039
6040    Function ${_MOZFUNC_UN}UnloadUAC
6041      ${Unless} ${AtLeastWinVista}
6042        Return
6043      ${EndUnless}
6044
6045      Push $R9
6046
6047      ClearErrors
6048      ${${_MOZFUNC_UN}GetParameters} $R9
6049      ${${_MOZFUNC_UN}GetOptions} "$R9" "/UAC:" $R9
6050      ; If the command line contains /UAC then we need to unload the UAC plugin
6051      IfErrors +2 +1
6052      UAC::Unload
6053
6054      ClearErrors
6055
6056      Pop $R9
6057    FunctionEnd
6058
6059    !verbose pop
6060  !endif
6061!macroend
6062
6063!macro UnloadUACCall
6064  !verbose push
6065  !verbose ${_MOZFUNC_VERBOSE}
6066  Call UnloadUAC
6067  !verbose pop
6068!macroend
6069
6070!macro un.UnloadUACCall
6071  !verbose push
6072  !verbose ${_MOZFUNC_VERBOSE}
6073  Call un.UnloadUAC
6074  !verbose pop
6075!macroend
6076
6077!macro un.UnloadUAC
6078  !ifndef un.UnloadUAC
6079    !verbose push
6080    !verbose ${_MOZFUNC_VERBOSE}
6081    !undef _MOZFUNC_UN
6082    !define _MOZFUNC_UN "un."
6083
6084    !insertmacro UnloadUAC
6085
6086    !undef _MOZFUNC_UN
6087    !define _MOZFUNC_UN
6088    !verbose pop
6089  !endif
6090!macroend
6091
6092
6093################################################################################
6094# Macros for uninstall.log and install.log logging
6095#
6096# Since these are used by other macros they should be inserted first. All of
6097# these macros can be easily inserted using the _LoggingCommon macro.
6098
6099/**
6100 * Adds all logging macros in the correct order in one fell swoop as well as
6101 * the vars for the install.log and uninstall.log file handles.
6102 */
6103!macro _LoggingCommon
6104  Var /GLOBAL fhInstallLog
6105  Var /GLOBAL fhUninstallLog
6106  !insertmacro StartInstallLog
6107  !insertmacro EndInstallLog
6108  !insertmacro StartUninstallLog
6109  !insertmacro EndUninstallLog
6110!macroend
6111!define _LoggingCommon "!insertmacro _LoggingCommon"
6112
6113/**
6114 * Creates a file named install.log in the install directory (e.g. $INSTDIR)
6115 * and adds the installation started message to the install.log for this
6116 * installation. This also adds the fhInstallLog and fhUninstallLog vars used
6117 * for logging.
6118 *
6119 * $fhInstallLog = filehandle for $INSTDIR\install.log
6120 *
6121 * @param   _APP_NAME
6122 *          Typically the BrandFullName
6123 * @param   _AB_CD
6124 *          The locale identifier
6125 * @param   _APP_VERSION
6126 *          The application version
6127 * @param   _GRE_VERSION
6128 *          The Gecko Runtime Engine version
6129 *
6130 * $R6 = _APP_NAME
6131 * $R7 = _AB_CD
6132 * $R8 = _APP_VERSION
6133 * $R9 = _GRE_VERSION
6134 */
6135!macro StartInstallLog
6136
6137  !ifndef StartInstallLog
6138    !insertmacro GetTime
6139
6140    !verbose push
6141    !verbose ${_MOZFUNC_VERBOSE}
6142    !define StartInstallLog "!insertmacro StartInstallLogCall"
6143
6144    Function StartInstallLog
6145      Exch $R9
6146      Exch 1
6147      Exch $R8
6148      Exch 2
6149      Exch $R7
6150      Exch 3
6151      Exch $R6
6152      Push $R5
6153      Push $R4
6154      Push $R3
6155      Push $R2
6156      Push $R1
6157      Push $R0
6158      Push $9
6159
6160      ${DeleteFile} "$INSTDIR\install.log"
6161      FileOpen $fhInstallLog "$INSTDIR\install.log" w
6162      FileWriteWord $fhInstallLog "65279"
6163
6164      ${GetTime} "" "L" $9 $R0 $R1 $R2 $R3 $R4 $R5
6165      FileWriteUTF16LE $fhInstallLog "$R6 Installation Started: $R1-$R0-$9 $R3:$R4:$R5"
6166      ${WriteLogSeparator}
6167
6168      ${LogHeader} "Installation Details"
6169      ${LogMsg} "Install Dir: $INSTDIR"
6170      ${LogMsg} "Locale     : $R7"
6171      ${LogMsg} "App Version: $R8"
6172      ${LogMsg} "GRE Version: $R9"
6173
6174      ${If} ${IsWinXP}
6175        ${LogMsg} "OS Name    : Windows XP"
6176      ${ElseIf} ${IsWin2003}
6177        ${LogMsg} "OS Name    : Windows 2003"
6178      ${ElseIf} ${IsWinVista}
6179        ${LogMsg} "OS Name    : Windows Vista"
6180      ${ElseIf} ${IsWin7}
6181        ${LogMsg} "OS Name    : Windows 7"
6182      ${ElseIf} ${IsWin8}
6183        ${LogMsg} "OS Name    : Windows 8"
6184      ${ElseIf} ${IsWin8.1}
6185        ${LogMsg} "OS Name    : Windows 8.1"
6186      ${ElseIf} ${IsWin10}
6187        ${LogMsg} "OS Name    : Windows 10"
6188      ${ElseIf} ${AtLeastWin10}
6189        ${LogMsg} "OS Name    : Above Windows 10"
6190      ${Else}
6191        ${LogMsg} "OS Name    : Unable to detect"
6192      ${EndIf}
6193
6194      !ifdef HAVE_64BIT_BUILD
6195        ${LogMsg} "Target CPU : x64"
6196      !else
6197        ${LogMsg} "Target CPU : x86"
6198      !endif
6199
6200      Pop $9
6201      Pop $R0
6202      Pop $R1
6203      Pop $R2
6204      Pop $R3
6205      Pop $R4
6206      Pop $R5
6207      Exch $R6
6208      Exch 3
6209      Exch $R7
6210      Exch 2
6211      Exch $R8
6212      Exch 1
6213      Exch $R9
6214    FunctionEnd
6215
6216    !verbose pop
6217  !endif
6218!macroend
6219
6220!macro StartInstallLogCall _APP_NAME _AB_CD _APP_VERSION _GRE_VERSION
6221  !verbose push
6222  !verbose ${_MOZFUNC_VERBOSE}
6223  Push "${_APP_NAME}"
6224  Push "${_AB_CD}"
6225  Push "${_APP_VERSION}"
6226  Push "${_GRE_VERSION}"
6227  Call StartInstallLog
6228  !verbose pop
6229!macroend
6230
6231/**
6232 * Writes the installation finished message to the install.log and closes the
6233 * file handles to the install.log and uninstall.log
6234 *
6235 * @param   _APP_NAME
6236 *
6237 * $R9 = _APP_NAME
6238 */
6239!macro EndInstallLog
6240
6241  !ifndef EndInstallLog
6242    !insertmacro GetTime
6243
6244    !verbose push
6245    !verbose ${_MOZFUNC_VERBOSE}
6246    !define EndInstallLog "!insertmacro EndInstallLogCall"
6247
6248    Function EndInstallLog
6249      Exch $R9
6250      Push $R8
6251      Push $R7
6252      Push $R6
6253      Push $R5
6254      Push $R4
6255      Push $R3
6256      Push $R2
6257
6258      ${WriteLogSeparator}
6259      ${GetTime} "" "L" $R2 $R3 $R4 $R5 $R6 $R7 $R8
6260      FileWriteUTF16LE $fhInstallLog "$R9 Installation Finished: $R4-$R3-$R2 $R6:$R7:$R8$\r$\n"
6261      FileClose $fhInstallLog
6262
6263      Pop $R2
6264      Pop $R3
6265      Pop $R4
6266      Pop $R5
6267      Pop $R6
6268      Pop $R7
6269      Pop $R8
6270      Exch $R9
6271    FunctionEnd
6272
6273    !verbose pop
6274  !endif
6275!macroend
6276
6277!macro EndInstallLogCall _APP_NAME
6278  !verbose push
6279  !verbose ${_MOZFUNC_VERBOSE}
6280  Push "${_APP_NAME}"
6281  Call EndInstallLog
6282  !verbose pop
6283!macroend
6284
6285/**
6286 * Opens the file handle to the uninstall.log.
6287 *
6288 * $fhUninstallLog = filehandle for $INSTDIR\uninstall\uninstall.log
6289 */
6290!macro StartUninstallLog
6291
6292  !ifndef StartUninstallLog
6293    !verbose push
6294    !verbose ${_MOZFUNC_VERBOSE}
6295    !define StartUninstallLog "!insertmacro StartUninstallLogCall"
6296
6297    Function StartUninstallLog
6298      FileOpen $fhUninstallLog "$INSTDIR\uninstall\uninstall.log" w
6299    FunctionEnd
6300
6301    !verbose pop
6302  !endif
6303!macroend
6304
6305!macro StartUninstallLogCall
6306  !verbose push
6307  !verbose ${_MOZFUNC_VERBOSE}
6308  Call StartUninstallLog
6309  !verbose pop
6310!macroend
6311
6312/**
6313 * Closes the file handle to the uninstall.log.
6314 */
6315!macro EndUninstallLog
6316
6317  !ifndef EndUninstallLog
6318
6319    !verbose push
6320    !verbose ${_MOZFUNC_VERBOSE}
6321    !define EndUninstallLog "!insertmacro EndUninstallLogCall"
6322
6323    Function EndUninstallLog
6324      FileClose $fhUninstallLog
6325    FunctionEnd
6326
6327    !verbose pop
6328  !endif
6329!macroend
6330
6331!macro EndUninstallLogCall
6332  !verbose push
6333  !verbose ${_MOZFUNC_VERBOSE}
6334  Call EndUninstallLog
6335  !verbose pop
6336!macroend
6337
6338/**
6339 * Adds a section header to the human readable log.
6340 *
6341 * @param   _HEADER
6342 *          The header text to write to the log.
6343 */
6344!macro LogHeader _HEADER
6345  ${WriteLogSeparator}
6346  FileWriteUTF16LE $fhInstallLog "${_HEADER}"
6347  ${WriteLogSeparator}
6348!macroend
6349!define LogHeader "!insertmacro LogHeader"
6350
6351/**
6352 * Adds a section message to the human readable log.
6353 *
6354 * @param   _MSG
6355 *          The message text to write to the log.
6356 */
6357!macro LogMsg _MSG
6358  FileWriteUTF16LE $fhInstallLog "  ${_MSG}$\r$\n"
6359!macroend
6360!define LogMsg "!insertmacro LogMsg"
6361
6362/**
6363 * Adds an uninstall entry to the uninstall log.
6364 *
6365 * @param   _MSG
6366 *          The message text to write to the log.
6367 */
6368!macro LogUninstall _MSG
6369  FileWrite $fhUninstallLog "${_MSG}$\r$\n"
6370!macroend
6371!define LogUninstall "!insertmacro LogUninstall"
6372
6373/**
6374 * Adds a section divider to the human readable log.
6375 */
6376!macro WriteLogSeparator
6377  FileWriteUTF16LE $fhInstallLog "$\r$\n----------------------------------------\
6378                                  ---------------------------------------$\r$\n"
6379!macroend
6380!define WriteLogSeparator "!insertmacro WriteLogSeparator"
6381
6382
6383################################################################################
6384# Macros for managing the shortcuts log ini file
6385
6386/**
6387 * Adds the most commonly used shortcut logging macros for the installer in one
6388 * fell swoop.
6389 */
6390!macro _LoggingShortcutsCommon
6391  !insertmacro LogDesktopShortcut
6392  !insertmacro LogQuickLaunchShortcut
6393  !insertmacro LogSMProgramsShortcut
6394!macroend
6395!define _LoggingShortcutsCommon "!insertmacro _LoggingShortcutsCommon"
6396
6397/**
6398 * Creates the shortcuts log ini file with a UTF-16LE BOM if it doesn't exist.
6399 */
6400!macro initShortcutsLog
6401  Push $R9
6402
6403  IfFileExists "$INSTDIR\uninstall\${SHORTCUTS_LOG}" +4 +1
6404  FileOpen $R9 "$INSTDIR\uninstall\${SHORTCUTS_LOG}" w
6405  FileWriteWord $R9 "65279"
6406  FileClose $R9
6407
6408  Pop $R9
6409!macroend
6410!define initShortcutsLog "!insertmacro initShortcutsLog"
6411
6412/**
6413 * Adds shortcut entries to the shortcuts log ini file. This macro is primarily
6414 * a helper used by the LogDesktopShortcut, LogQuickLaunchShortcut, and
6415 * LogSMProgramsShortcut macros but it can be used by other code if desired. If
6416 * the value already exists the the value is not written to the file.
6417 *
6418 * @param   _SECTION_NAME
6419 *          The section name to write to in the shortcut log ini file
6420 * @param   _FILE_NAME
6421 *          The shortcut's file name
6422 *
6423 * $R6 = return value from ReadIniStr for the shortcut file name
6424 * $R7 = counter for supporting multiple shortcuts in the same location
6425 * $R8 = _SECTION_NAME
6426 * $R9 = _FILE_NAME
6427 */
6428!macro LogShortcut
6429
6430  !ifndef LogShortcut
6431    !verbose push
6432    !verbose ${_MOZFUNC_VERBOSE}
6433    !define LogShortcut "!insertmacro LogShortcutCall"
6434
6435    Function LogShortcut
6436      Exch $R9
6437      Exch 1
6438      Exch $R8
6439      Push $R7
6440      Push $R6
6441
6442      ClearErrors
6443
6444      !insertmacro initShortcutsLog
6445
6446      StrCpy $R6 ""
6447      StrCpy $R7 -1
6448
6449      StrCmp "$R6" "$R9" +5 +1 ; if the shortcut already exists don't add it
6450      IntOp $R7 $R7 + 1 ; increment the counter
6451      ReadIniStr $R6 "$INSTDIR\uninstall\${SHORTCUTS_LOG}" "$R8" "Shortcut$R7"
6452      IfErrors +1 -3
6453      WriteINIStr "$INSTDIR\uninstall\${SHORTCUTS_LOG}" "$R8" "Shortcut$R7" "$R9"
6454
6455      ClearErrors
6456
6457      Pop $R6
6458      Pop $R7
6459      Exch $R8
6460      Exch 1
6461      Exch $R9
6462    FunctionEnd
6463
6464    !verbose pop
6465  !endif
6466!macroend
6467
6468!macro LogShortcutCall _SECTION_NAME _FILE_NAME
6469  !verbose push
6470  !verbose ${_MOZFUNC_VERBOSE}
6471  Push "${_SECTION_NAME}"
6472  Push "${_FILE_NAME}"
6473  Call LogShortcut
6474  !verbose pop
6475!macroend
6476
6477/**
6478 * Adds a Desktop shortcut entry to the shortcuts log ini file.
6479 *
6480 * @param   _FILE_NAME
6481 *          The shortcut file name (e.g. shortcut.lnk)
6482 */
6483!macro LogDesktopShortcut
6484
6485  !ifndef LogDesktopShortcut
6486    !insertmacro LogShortcut
6487
6488    !verbose push
6489    !verbose ${_MOZFUNC_VERBOSE}
6490    !define LogDesktopShortcut "!insertmacro LogDesktopShortcutCall"
6491
6492    Function LogDesktopShortcut
6493      Call LogShortcut
6494    FunctionEnd
6495
6496    !verbose pop
6497  !endif
6498!macroend
6499
6500!macro LogDesktopShortcutCall _FILE_NAME
6501  !verbose push
6502  !verbose ${_MOZFUNC_VERBOSE}
6503  Push "DESKTOP"
6504  Push "${_FILE_NAME}"
6505  Call LogDesktopShortcut
6506  !verbose pop
6507!macroend
6508
6509/**
6510 * Adds a QuickLaunch shortcut entry to the shortcuts log ini file.
6511 *
6512 * @param   _FILE_NAME
6513 *          The shortcut file name (e.g. shortcut.lnk)
6514 */
6515!macro LogQuickLaunchShortcut
6516
6517  !ifndef LogQuickLaunchShortcut
6518    !insertmacro LogShortcut
6519
6520    !verbose push
6521    !verbose ${_MOZFUNC_VERBOSE}
6522    !define LogQuickLaunchShortcut "!insertmacro LogQuickLaunchShortcutCall"
6523
6524    Function LogQuickLaunchShortcut
6525      Call LogShortcut
6526    FunctionEnd
6527
6528    !verbose pop
6529  !endif
6530!macroend
6531
6532!macro LogQuickLaunchShortcutCall _FILE_NAME
6533  !verbose push
6534  !verbose ${_MOZFUNC_VERBOSE}
6535  Push "QUICKLAUNCH"
6536  Push "${_FILE_NAME}"
6537  Call LogQuickLaunchShortcut
6538  !verbose pop
6539!macroend
6540
6541/**
6542 * Adds a Start Menu shortcut entry to the shortcuts log ini file.
6543 *
6544 * @param   _FILE_NAME
6545 *          The shortcut file name (e.g. shortcut.lnk)
6546 */
6547!macro LogStartMenuShortcut
6548
6549  !ifndef LogStartMenuShortcut
6550    !insertmacro LogShortcut
6551
6552    !verbose push
6553    !verbose ${_MOZFUNC_VERBOSE}
6554    !define LogStartMenuShortcut "!insertmacro LogStartMenuShortcutCall"
6555
6556    Function LogStartMenuShortcut
6557      Call LogShortcut
6558    FunctionEnd
6559
6560    !verbose pop
6561  !endif
6562!macroend
6563
6564!macro LogStartMenuShortcutCall _FILE_NAME
6565  !verbose push
6566  !verbose ${_MOZFUNC_VERBOSE}
6567  Push "STARTMENU"
6568  Push "${_FILE_NAME}"
6569  Call LogStartMenuShortcut
6570  !verbose pop
6571!macroend
6572
6573/**
6574 * Adds a Start Menu Programs shortcut entry to the shortcuts log ini file.
6575 *
6576 * @param   _FILE_NAME
6577 *          The shortcut file name (e.g. shortcut.lnk)
6578 */
6579!macro LogSMProgramsShortcut
6580
6581  !ifndef LogSMProgramsShortcut
6582    !insertmacro LogShortcut
6583
6584    !verbose push
6585    !verbose ${_MOZFUNC_VERBOSE}
6586    !define LogSMProgramsShortcut "!insertmacro LogSMProgramsShortcutCall"
6587
6588    Function LogSMProgramsShortcut
6589      Call LogShortcut
6590    FunctionEnd
6591
6592    !verbose pop
6593  !endif
6594!macroend
6595
6596!macro LogSMProgramsShortcutCall _FILE_NAME
6597  !verbose push
6598  !verbose ${_MOZFUNC_VERBOSE}
6599  Push "SMPROGRAMS"
6600  Push "${_FILE_NAME}"
6601  Call LogSMProgramsShortcut
6602  !verbose pop
6603!macroend
6604
6605/**
6606 * Adds the relative path from the Start Menu Programs directory for the
6607 * application's Start Menu directory if it is different from the existing value
6608 * to the shortcuts log ini file.
6609 *
6610 * @param   _REL_PATH_TO_DIR
6611 *          The relative path from the Start Menu Programs directory to the
6612 *          program's directory.
6613 *
6614 * $R9 = _REL_PATH_TO_DIR
6615 */
6616!macro LogSMProgramsDirRelPath _REL_PATH_TO_DIR
6617  Push $R9
6618
6619  !insertmacro initShortcutsLog
6620
6621  ReadINIStr $R9 "$INSTDIR\uninstall\${SHORTCUTS_LOG}" "SMPROGRAMS" "RelativePathToDir"
6622  StrCmp "$R9" "${_REL_PATH_TO_DIR}" +2 +1
6623  WriteINIStr "$INSTDIR\uninstall\${SHORTCUTS_LOG}" "SMPROGRAMS" "RelativePathToDir" "${_REL_PATH_TO_DIR}"
6624
6625  Pop $R9
6626!macroend
6627!define LogSMProgramsDirRelPath "!insertmacro LogSMProgramsDirRelPath"
6628
6629/**
6630 * Copies the value for the relative path from the Start Menu programs directory
6631 * (e.g. $SMPROGRAMS) to the Start Menu directory as it is stored in the
6632 * shortcuts log ini file to the variable specified in the first parameter.
6633 */
6634!macro GetSMProgramsDirRelPath _VAR
6635  ReadINIStr ${_VAR} "$INSTDIR\uninstall\${SHORTCUTS_LOG}" "SMPROGRAMS" \
6636             "RelativePathToDir"
6637!macroend
6638!define GetSMProgramsDirRelPath "!insertmacro GetSMProgramsDirRelPath"
6639
6640/**
6641 * Copies the shortcuts log ini file path to the variable specified in the
6642 * first parameter.
6643 */
6644!macro GetShortcutsLogPath _VAR
6645  StrCpy ${_VAR} "$INSTDIR\uninstall\${SHORTCUTS_LOG}"
6646!macroend
6647!define GetShortcutsLogPath "!insertmacro GetShortcutsLogPath"
6648
6649/**
6650 * Deletes the shortcuts log ini file.
6651 */
6652!macro DeleteShortcutsLogFile
6653  ${DeleteFile} "$INSTDIR\uninstall\${SHORTCUTS_LOG}"
6654!macroend
6655!define DeleteShortcutsLogFile "!insertmacro DeleteShortcutsLogFile"
6656
6657
6658################################################################################
6659# Macros for managing specific Windows version features
6660
6661/**
6662 * Sets the permitted layered service provider (LSP) categories on Windows
6663 * Vista and above for the application. Consumers should call this after an
6664 * installation log section has completed since this macro will log the results
6665 * to the installation log along with a header.
6666 *
6667 * !IMPORTANT - When calling this macro from an uninstaller do not specify a
6668 *              parameter. The paramter is hardcoded with 0x00000000 to remove
6669 *              the LSP category for the application when performing an
6670 *              uninstall.
6671 *
6672 * @param   _LSP_CATEGORIES
6673 *          The permitted LSP categories for the application. When called by an
6674 *          uninstaller this will always be 0x00000000.
6675 *
6676 * $R5 = error code popped from the stack for the WSCSetApplicationCategory call
6677 * $R6 = return value from the WSCSetApplicationCategory call
6678 * $R7 = string length for the long path to the main application executable
6679 * $R8 = long path to the main application executable
6680 * $R9 = _LSP_CATEGORIES
6681 */
6682!macro SetAppLSPCategories
6683
6684  !ifndef ${_MOZFUNC_UN}SetAppLSPCategories
6685    !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN}
6686    !insertmacro ${_MOZFUNC_UN_TMP}GetLongPath
6687    !undef _MOZFUNC_UN
6688    !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP}
6689    !undef _MOZFUNC_UN_TMP
6690
6691    !verbose push
6692    !verbose ${_MOZFUNC_VERBOSE}
6693    !define ${_MOZFUNC_UN}SetAppLSPCategories "!insertmacro ${_MOZFUNC_UN}SetAppLSPCategoriesCall"
6694
6695    Function ${_MOZFUNC_UN}SetAppLSPCategories
6696      ${Unless} ${AtLeastWinVista}
6697        Return
6698      ${EndUnless}
6699
6700      Exch $R9
6701      Push $R8
6702      Push $R7
6703      Push $R6
6704      Push $R5
6705
6706      ${${_MOZFUNC_UN}GetLongPath} "$INSTDIR\${FileMainEXE}" $R8
6707      StrLen $R7 "$R8"
6708
6709      ; Remove existing categories by setting the permitted categories to
6710      ; 0x00000000 since new categories are ANDed with existing categories. If
6711      ; the param value stored in $R9 is 0x00000000 then skip the removal since
6712      ; the categories  will be removed by the second call to
6713      ; WSCSetApplicationCategory.
6714      StrCmp "$R9" "0x00000000" +2 +1
6715      System::Call "Ws2_32::WSCSetApplicationCategory(w R8, i R7, w n, i 0,\
6716                                                      i 0x00000000, i n, *i) i"
6717
6718      ; Set the permitted LSP categories
6719      System::Call "Ws2_32::WSCSetApplicationCategory(w R8, i R7, w n, i 0,\
6720                                                      i R9, i n, *i .s) i.R6"
6721      Pop $R5
6722
6723!ifndef NO_LOG
6724      ${LogHeader} "Setting Permitted LSP Categories"
6725      StrCmp "$R6" 0 +3 +1
6726      ${LogMsg} "** ERROR Setting LSP Categories: $R5 **"
6727      GoTo +2
6728      ${LogMsg} "Permitted LSP Categories: $R9"
6729!endif
6730
6731      ClearErrors
6732
6733      Pop $R5
6734      Pop $R6
6735      Pop $R7
6736      Pop $R8
6737      Exch $R9
6738    FunctionEnd
6739
6740    !verbose pop
6741  !endif
6742!macroend
6743
6744!macro SetAppLSPCategoriesCall _LSP_CATEGORIES
6745  !verbose push
6746  !verbose ${_MOZFUNC_VERBOSE}
6747  Push "${_LSP_CATEGORIES}"
6748  Call SetAppLSPCategories
6749  !verbose pop
6750!macroend
6751
6752!macro un.SetAppLSPCategoriesCall
6753  !verbose push
6754  !verbose ${_MOZFUNC_VERBOSE}
6755  Push "0x00000000"
6756  Call un.SetAppLSPCategories
6757  !verbose pop
6758!macroend
6759
6760!macro un.SetAppLSPCategories
6761  !ifndef un.SetAppLSPCategories
6762    !verbose push
6763    !verbose ${_MOZFUNC_VERBOSE}
6764    !undef _MOZFUNC_UN
6765    !define _MOZFUNC_UN "un."
6766
6767    !insertmacro SetAppLSPCategories
6768
6769    !undef _MOZFUNC_UN
6770    !define _MOZFUNC_UN
6771    !verbose pop
6772  !endif
6773!macroend
6774
6775/**
6776 * Checks if any pinned TaskBar lnk files point to the executable's path passed
6777 * to the macro.
6778 *
6779 * @param   _EXE_PATH
6780 *          The executable path
6781 * @return  _RESULT
6782 *          false if no pinned shotcuts were found for this install location.
6783 *          true if pinned shotcuts were found for this install location.
6784 *
6785 * $R5 = stores whether a TaskBar lnk file has been found for the executable
6786 * $R6 = long path returned from GetShortCutTarget and GetLongPath
6787 * $R7 = file name returned from FindFirst and FindNext
6788 * $R8 = find handle for FindFirst and FindNext
6789 * $R9 = _EXE_PATH and _RESULT
6790 */
6791!macro IsPinnedToTaskBar
6792
6793  !ifndef IsPinnedToTaskBar
6794    !insertmacro GetLongPath
6795
6796    !verbose push
6797    !verbose ${_MOZFUNC_VERBOSE}
6798    !define IsPinnedToTaskBar "!insertmacro IsPinnedToTaskBarCall"
6799
6800    Function IsPinnedToTaskBar
6801      Exch $R9
6802      Push $R8
6803      Push $R7
6804      Push $R6
6805      Push $R5
6806
6807      StrCpy $R5 "false"
6808
6809      ${If} ${AtLeastWin7}
6810      ${AndIf} ${FileExists} "$QUICKLAUNCH\User Pinned\TaskBar"
6811        FindFirst $R8 $R7 "$QUICKLAUNCH\User Pinned\TaskBar\*.lnk"
6812        ${Do}
6813          ${If} ${FileExists} "$QUICKLAUNCH\User Pinned\TaskBar\$R7"
6814            ShellLink::GetShortCutTarget "$QUICKLAUNCH\User Pinned\TaskBar\$R7"
6815            Pop $R6
6816            ${GetLongPath} "$R6" $R6
6817            ${If} "$R6" == "$R9"
6818              StrCpy $R5 "true"
6819              ${ExitDo}
6820            ${EndIf}
6821          ${EndIf}
6822          ClearErrors
6823          FindNext $R8 $R7
6824          ${If} ${Errors}
6825            ${ExitDo}
6826          ${EndIf}
6827        ${Loop}
6828        FindClose $R8
6829      ${EndIf}
6830
6831      ClearErrors
6832
6833      StrCpy $R9 $R5
6834
6835      Pop $R5
6836      Pop $R6
6837      Pop $R7
6838      Pop $R8
6839      Exch $R9
6840    FunctionEnd
6841
6842    !verbose pop
6843  !endif
6844!macroend
6845
6846!macro IsPinnedToTaskBarCall _EXE_PATH _RESULT
6847  !verbose push
6848  !verbose ${_MOZFUNC_VERBOSE}
6849  Push "${_EXE_PATH}"
6850  Call IsPinnedToTaskBar
6851  Pop ${_RESULT}
6852  !verbose pop
6853!macroend
6854
6855/**
6856 * Checks if any pinned Start Menu lnk files point to the executable's path
6857 * passed to the macro.
6858 *
6859 * @param   _EXE_PATH
6860 *          The executable path
6861 * @return  _RESULT
6862 *          false if no pinned shotcuts were found for this install location.
6863 *          true if pinned shotcuts were found for this install location.
6864 *
6865 * $R5 = stores whether a Start Menu lnk file has been found for the executable
6866 * $R6 = long path returned from GetShortCutTarget and GetLongPath
6867 * $R7 = file name returned from FindFirst and FindNext
6868 * $R8 = find handle for FindFirst and FindNext
6869 * $R9 = _EXE_PATH and _RESULT
6870 */
6871!macro IsPinnedToStartMenu
6872
6873  !ifndef IsPinnedToStartMenu
6874    !insertmacro GetLongPath
6875
6876    !verbose push
6877    !verbose ${_MOZFUNC_VERBOSE}
6878    !define IsPinnedToStartMenu "!insertmacro IsPinnedToStartMenuCall"
6879
6880    Function IsPinnedToStartMenu
6881      Exch $R9
6882      Push $R8
6883      Push $R7
6884      Push $R6
6885      Push $R5
6886
6887      StrCpy $R5 "false"
6888
6889      ${If} ${AtLeastWin7}
6890      ${AndIf} ${FileExists} "$QUICKLAUNCH\User Pinned\StartMenu"
6891        FindFirst $R8 $R7 "$QUICKLAUNCH\User Pinned\StartMenu\*.lnk"
6892        ${Do}
6893          ${If} ${FileExists} "$QUICKLAUNCH\User Pinned\StartMenu\$R7"
6894            ShellLink::GetShortCutTarget "$QUICKLAUNCH\User Pinned\StartMenu\$R7"
6895            Pop $R6
6896            ${GetLongPath} "$R6" $R6
6897            ${If} "$R6" == "$R9"
6898              StrCpy $R5 "true"
6899              ${ExitDo}
6900            ${EndIf}
6901          ${EndIf}
6902          ClearErrors
6903          FindNext $R8 $R7
6904          ${If} ${Errors}
6905            ${ExitDo}
6906          ${EndIf}
6907        ${Loop}
6908        FindClose $R8
6909      ${EndIf}
6910
6911      ClearErrors
6912
6913      StrCpy $R9 $R5
6914
6915      Pop $R5
6916      Pop $R6
6917      Pop $R7
6918      Pop $R8
6919      Exch $R9
6920    FunctionEnd
6921
6922    !verbose pop
6923  !endif
6924!macroend
6925
6926!macro IsPinnedToStartMenuCall _EXE_PATH _RESULT
6927  !verbose push
6928  !verbose ${_MOZFUNC_VERBOSE}
6929  Push "${_EXE_PATH}"
6930  Call IsPinnedToStartMenu
6931  Pop ${_RESULT}
6932  !verbose pop
6933!macroend
6934
6935/**
6936 * Gets the number of pinned shortcut lnk files pinned to the Task Bar.
6937 *
6938 * @return  _RESULT
6939 *          number of pinned shortcut lnk files.
6940 *
6941 * $R7 = file name returned from FindFirst and FindNext
6942 * $R8 = find handle for FindFirst and FindNext
6943 * $R9 = _RESULT
6944 */
6945!macro PinnedToTaskBarLnkCount
6946
6947  !ifndef PinnedToTaskBarLnkCount
6948    !insertmacro GetLongPath
6949
6950    !verbose push
6951    !verbose ${_MOZFUNC_VERBOSE}
6952    !define PinnedToTaskBarLnkCount "!insertmacro PinnedToTaskBarLnkCountCall"
6953
6954    Function PinnedToTaskBarLnkCount
6955      Push $R9
6956      Push $R8
6957      Push $R7
6958
6959      StrCpy $R9 0
6960
6961      ${If} ${AtLeastWin7}
6962      ${AndIf} ${FileExists} "$QUICKLAUNCH\User Pinned\TaskBar"
6963        FindFirst $R8 $R7 "$QUICKLAUNCH\User Pinned\TaskBar\*.lnk"
6964        ${Do}
6965          ${If} ${FileExists} "$QUICKLAUNCH\User Pinned\TaskBar\$R7"
6966            IntOp $R9 $R9 + 1
6967          ${EndIf}
6968          ClearErrors
6969          FindNext $R8 $R7
6970          ${If} ${Errors}
6971            ${ExitDo}
6972          ${EndIf}
6973        ${Loop}
6974        FindClose $R8
6975      ${EndIf}
6976
6977      ClearErrors
6978
6979      Pop $R7
6980      Pop $R8
6981      Exch $R9
6982    FunctionEnd
6983
6984    !verbose pop
6985  !endif
6986!macroend
6987
6988!macro PinnedToTaskBarLnkCountCall _RESULT
6989  !verbose push
6990  !verbose ${_MOZFUNC_VERBOSE}
6991  Call PinnedToTaskBarLnkCount
6992  Pop ${_RESULT}
6993  !verbose pop
6994!macroend
6995
6996/**
6997 * Gets the number of pinned shortcut lnk files pinned to the Start Menu.
6998 *
6999 * @return  _RESULT
7000 *          number of pinned shortcut lnk files.
7001 *
7002 * $R7 = file name returned from FindFirst and FindNext
7003 * $R8 = find handle for FindFirst and FindNext
7004 * $R9 = _RESULT
7005 */
7006!macro PinnedToStartMenuLnkCount
7007
7008  !ifndef PinnedToStartMenuLnkCount
7009    !insertmacro GetLongPath
7010
7011    !verbose push
7012    !verbose ${_MOZFUNC_VERBOSE}
7013    !define PinnedToStartMenuLnkCount "!insertmacro PinnedToStartMenuLnkCountCall"
7014
7015    Function PinnedToStartMenuLnkCount
7016      Push $R9
7017      Push $R8
7018      Push $R7
7019
7020      StrCpy $R9 0
7021
7022      ${If} ${AtLeastWin7}
7023      ${AndIf} ${FileExists} "$QUICKLAUNCH\User Pinned\StartMenu"
7024        FindFirst $R8 $R7 "$QUICKLAUNCH\User Pinned\StartMenu\*.lnk"
7025        ${Do}
7026          ${If} ${FileExists} "$QUICKLAUNCH\User Pinned\StartMenu\$R7"
7027            IntOp $R9 $R9 + 1
7028          ${EndIf}
7029          ClearErrors
7030          FindNext $R8 $R7
7031          ${If} ${Errors}
7032            ${ExitDo}
7033          ${EndIf}
7034        ${Loop}
7035        FindClose $R8
7036      ${EndIf}
7037
7038      ClearErrors
7039
7040      Pop $R7
7041      Pop $R8
7042      Exch $R9
7043    FunctionEnd
7044
7045    !verbose pop
7046  !endif
7047!macroend
7048
7049!macro PinnedToStartMenuLnkCountCall _RESULT
7050  !verbose push
7051  !verbose ${_MOZFUNC_VERBOSE}
7052  Call PinnedToStartMenuLnkCount
7053  Pop ${_RESULT}
7054  !verbose pop
7055!macroend
7056
7057/**
7058 * Update Start Menu / TaskBar lnk files that point to the executable's path
7059 * passed to the macro and all other shortcuts installed by the application with
7060 * the current application user model ID. Requires ApplicationID.
7061 *
7062 * NOTE: this does not update Desktop shortcut application user model ID due to
7063 *       bug 633728.
7064 *
7065 * @param   _EXE_PATH
7066 *          The main application executable path
7067 * @param   _APP_ID
7068 *          The application user model ID for the current install
7069 * @return  _RESULT
7070 *          false if no pinned shotcuts were found for this install location.
7071 *          true if pinned shotcuts were found for this install location.
7072 */
7073!macro UpdateShortcutAppModelIDs
7074
7075  !ifndef UpdateShortcutAppModelIDs
7076    !insertmacro GetLongPath
7077
7078    !verbose push
7079    !verbose ${_MOZFUNC_VERBOSE}
7080    !define UpdateShortcutAppModelIDs "!insertmacro UpdateShortcutAppModelIDsCall"
7081
7082    Function UpdateShortcutAppModelIDs
7083      ; stack: path, appid
7084      Exch $R9 ; stack: $R9, appid | $R9 = path
7085      Exch 1   ; stack: appid, $R9
7086      Exch $R8 ; stack: $R8, $R9   | $R8 = appid
7087      Push $R7 ; stack: $R7, $R8, $R9
7088      Push $R6
7089      Push $R5
7090      Push $R4
7091      Push $R3 ; stack: $R3, $R5, $R6, $R7, $R8, $R9
7092      Push $R2
7093
7094      ; $R9 = main application executable path
7095      ; $R8 = appid
7096      ; $R7 = path to the application's start menu programs directory
7097      ; $R6 = path to the shortcut log ini file
7098      ; $R5 = shortcut filename
7099      ; $R4 = GetShortCutTarget result
7100
7101      StrCpy $R3 "false"
7102
7103      ${If} ${AtLeastWin7}
7104        ; installed shortcuts
7105        ${${_MOZFUNC_UN}GetLongPath} "$INSTDIR\uninstall\${SHORTCUTS_LOG}" $R6
7106        ${If} ${FileExists} "$R6"
7107          ; Update the Start Menu shortcuts' App ID for this application
7108          StrCpy $R2 -1
7109          ${Do}
7110            IntOp $R2 $R2 + 1 ; Increment the counter
7111            ClearErrors
7112            ReadINIStr $R5 "$R6" "STARTMENU" "Shortcut$R2"
7113            ${If} ${Errors}
7114              ${ExitDo}
7115            ${EndIf}
7116
7117            ${If} ${FileExists} "$SMPROGRAMS\$R5"
7118              ShellLink::GetShortCutTarget "$SMPROGRAMS\$$R5"
7119              Pop $R4
7120              ${GetLongPath} "$R4" $R4
7121              ${If} "$R4" == "$R9" ; link path == install path
7122                ApplicationID::Set "$SMPROGRAMS\$R5" "$R8"
7123                Pop $R4
7124              ${EndIf}
7125            ${EndIf}
7126          ${Loop}
7127
7128          ; Update the Quick Launch shortcuts' App ID for this application
7129          StrCpy $R2 -1
7130          ${Do}
7131            IntOp $R2 $R2 + 1 ; Increment the counter
7132            ClearErrors
7133            ReadINIStr $R5 "$R6" "QUICKLAUNCH" "Shortcut$R2"
7134            ${If} ${Errors}
7135              ${ExitDo}
7136            ${EndIf}
7137
7138            ${If} ${FileExists} "$QUICKLAUNCH\$R5"
7139              ShellLink::GetShortCutTarget "$QUICKLAUNCH\$R5"
7140              Pop $R4
7141              ${GetLongPath} "$R4" $R4
7142              ${If} "$R4" == "$R9" ; link path == install path
7143                ApplicationID::Set "$QUICKLAUNCH\$R5" "$R8"
7144                Pop $R4
7145              ${EndIf}
7146            ${EndIf}
7147          ${Loop}
7148
7149          ; Update the Start Menu Programs shortcuts' App ID for this application
7150          ClearErrors
7151          ReadINIStr $R7 "$R6" "SMPROGRAMS" "RelativePathToDir"
7152          ${Unless} ${Errors}
7153            ${${_MOZFUNC_UN}GetLongPath} "$SMPROGRAMS\$R7" $R7
7154            ${Unless} "$R7" == ""
7155              StrCpy $R2 -1
7156              ${Do}
7157                IntOp $R2 $R2 + 1 ; Increment the counter
7158                ClearErrors
7159                ReadINIStr $R5 "$R6" "SMPROGRAMS" "Shortcut$R2"
7160                ${If} ${Errors}
7161                  ${ExitDo}
7162                ${EndIf}
7163
7164                ${If} ${FileExists} "$R7\$R5"
7165                  ShellLink::GetShortCutTarget "$R7\$R5"
7166                  Pop $R4
7167                  ${GetLongPath} "$R4" $R4
7168                  ${If} "$R4" == "$R9" ; link path == install path
7169                    ApplicationID::Set "$R7\$R5" "$R8"
7170                    Pop $R4
7171                  ${EndIf}
7172                ${EndIf}
7173              ${Loop}
7174            ${EndUnless}
7175          ${EndUnless}
7176        ${EndIf}
7177
7178        StrCpy $R7 "$QUICKLAUNCH\User Pinned"
7179        StrCpy $R3 "false"
7180
7181        ; $R9 = main application executable path
7182        ; $R8 = appid
7183        ; $R7 = user pinned path
7184        ; $R6 = find handle
7185        ; $R5 = found filename
7186        ; $R4 = GetShortCutTarget result
7187
7188        ; TaskBar links
7189        FindFirst $R6 $R5 "$R7\TaskBar\*.lnk"
7190        ${Do}
7191          ${If} ${FileExists} "$R7\TaskBar\$R5"
7192            ShellLink::GetShortCutTarget "$R7\TaskBar\$R5"
7193            Pop $R4
7194            ${If} "$R4" == "$R9" ; link path == install path
7195              ApplicationID::Set "$R7\TaskBar\$R5" "$R8"
7196              Pop $R4 ; pop Set result off the stack
7197              StrCpy $R3 "true"
7198            ${EndIf}
7199          ${EndIf}
7200          ClearErrors
7201          FindNext $R6 $R5
7202          ${If} ${Errors}
7203            ${ExitDo}
7204          ${EndIf}
7205        ${Loop}
7206        FindClose $R6
7207
7208        ; Start menu links
7209        FindFirst $R6 $R5 "$R7\StartMenu\*.lnk"
7210        ${Do}
7211          ${If} ${FileExists} "$R7\StartMenu\$R5"
7212            ShellLink::GetShortCutTarget "$R7\StartMenu\$R5"
7213            Pop $R4
7214            ${If} "$R4" == "$R9" ; link path == install path
7215              ApplicationID::Set "$R7\StartMenu\$R5" "$R8"
7216              Pop $R4 ; pop Set result off the stack
7217              StrCpy $R3 "true"
7218            ${EndIf}
7219          ${EndIf}
7220          ClearErrors
7221          FindNext $R6 $R5
7222          ${If} ${Errors}
7223            ${ExitDo}
7224          ${EndIf}
7225        ${Loop}
7226        FindClose $R6
7227      ${EndIf}
7228
7229      ClearErrors
7230
7231      StrCpy $R9 $R3
7232
7233      Pop $R2
7234      Pop $R3  ; stack: $R4, $R5, $R6, $R7, $R8, $R9
7235      Pop $R4  ; stack: $R5, $R6, $R7, $R8, $R9
7236      Pop $R5  ; stack: $R6, $R7, $R8, $R9
7237      Pop $R6  ; stack: $R7, $R8, $R9
7238      Pop $R7  ; stack: $R8, $R9
7239      Exch $R8 ; stack: appid, $R9 | $R8 = old $R8
7240      Exch 1   ; stack: $R9, appid
7241      Exch $R9 ; stack: path, appid | $R9 = old $R9
7242    FunctionEnd
7243
7244    !verbose pop
7245  !endif
7246!macroend
7247
7248!macro UpdateShortcutAppModelIDsCall _EXE_PATH _APP_ID _RESULT
7249  !verbose push
7250  !verbose ${_MOZFUNC_VERBOSE}
7251  Push "${_APP_ID}"
7252  Push "${_EXE_PATH}"
7253  Call UpdateShortcutAppModelIDs
7254  Pop ${_RESULT}
7255  !verbose pop
7256!macroend
7257
7258!macro IsUserAdmin
7259  ; Copied from: http://nsis.sourceforge.net/IsUserAdmin
7260  Function IsUserAdmin
7261    Push $R0
7262    Push $R1
7263    Push $R2
7264
7265    ClearErrors
7266    UserInfo::GetName
7267    IfErrors Win9x
7268    Pop $R1
7269    UserInfo::GetAccountType
7270    Pop $R2
7271
7272    StrCmp $R2 "Admin" 0 Continue
7273    StrCpy $R0 "true"
7274    Goto Done
7275
7276    Continue:
7277
7278    StrCmp $R2 "" Win9x
7279    StrCpy $R0 "false"
7280    Goto Done
7281
7282    Win9x:
7283    StrCpy $R0 "true"
7284
7285    Done:
7286    Pop $R2
7287    Pop $R1
7288    Exch $R0
7289  FunctionEnd
7290!macroend
7291
7292/**
7293 * Retrieve if present or generate and store a 64 bit hash of an install path
7294 * using the City Hash algorithm.  On return the resulting id is saved in the
7295 * $AppUserModelID variable declared by inserting this macro. InitHashAppModelId
7296 * will attempt to load from HKLM/_REG_PATH first, then HKCU/_REG_PATH. If found
7297 * in either it will return the hash it finds. If not found it will generate a
7298 * new hash and attempt to store the hash in HKLM/_REG_PATH, then HKCU/_REG_PATH.
7299 * Subsequent calls will then retreive the stored hash value. On any failure,
7300 * $AppUserModelID will be set to an empty string.
7301 *
7302 * Registry format: root/_REG_PATH/"_EXE_PATH" = "hash"
7303 *
7304 * @param   _EXE_PATH
7305 *          The main application executable path
7306 * @param   _REG_PATH
7307 *          The HKLM/HKCU agnostic registry path where the key hash should
7308 *          be stored. ex: "Software\Mozilla\Firefox\TaskBarIDs"
7309 * @result  (Var) $AppUserModelID contains the app model id.
7310 */
7311!macro InitHashAppModelId
7312  !ifndef ${_MOZFUNC_UN}InitHashAppModelId
7313    !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN}
7314    !insertmacro ${_MOZFUNC_UN_TMP}GetLongPath
7315    !undef _MOZFUNC_UN
7316    !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP}
7317    !undef _MOZFUNC_UN_TMP
7318
7319    !ifndef InitHashAppModelId
7320      Var AppUserModelID
7321    !endif
7322
7323    !verbose push
7324    !verbose ${_MOZFUNC_VERBOSE}
7325    !define ${_MOZFUNC_UN}InitHashAppModelId "!insertmacro ${_MOZFUNC_UN}InitHashAppModelIdCall"
7326
7327    Function ${_MOZFUNC_UN}InitHashAppModelId
7328      ; stack: apppath, regpath
7329      Exch $R9 ; stack: $R9, regpath | $R9 = apppath
7330      Exch 1   ; stack: regpath, $R9
7331      Exch $R8 ; stack: $R8, $R9   | $R8 = regpath
7332      Push $R7
7333
7334      ${If} ${AtLeastWin7}
7335        ${${_MOZFUNC_UN}GetLongPath} "$R9" $R9
7336        ; Always create a new AppUserModelID and overwrite the existing one
7337        ; for the current installation path.
7338        CityHash::GetCityHash64 "$R9"
7339        Pop $AppUserModelID
7340        ${If} $AppUserModelID == "error"
7341          GoTo end
7342        ${EndIf}
7343        ClearErrors
7344        WriteRegStr HKLM "$R8" "$R9" "$AppUserModelID"
7345        ${If} ${Errors}
7346          ClearErrors
7347          WriteRegStr HKCU "$R8" "$R9" "$AppUserModelID"
7348          ${If} ${Errors}
7349            StrCpy $AppUserModelID "error"
7350          ${EndIf}
7351        ${EndIf}
7352      ${EndIf}
7353
7354      end:
7355      ${If} "$AppUserModelID" == "error"
7356        StrCpy $AppUserModelID ""
7357      ${EndIf}
7358
7359      ClearErrors
7360      Pop $R7
7361      Exch $R8
7362      Exch 1
7363      Exch $R9
7364    FunctionEnd
7365
7366    !verbose pop
7367  !endif
7368!macroend
7369
7370!macro InitHashAppModelIdCall _EXE_PATH _REG_PATH
7371  !verbose push
7372  !verbose ${_MOZFUNC_VERBOSE}
7373  Push "${_REG_PATH}"
7374  Push "${_EXE_PATH}"
7375  Call InitHashAppModelId
7376  !verbose pop
7377!macroend
7378
7379!macro un.InitHashAppModelIdCall _EXE_PATH _REG_PATH
7380  !verbose push
7381  !verbose ${_MOZFUNC_VERBOSE}
7382  Push "${_REG_PATH}"
7383  Push "${_EXE_PATH}"
7384  Call un.InitHashAppModelId
7385  !verbose pop
7386!macroend
7387
7388!macro un.InitHashAppModelId
7389  !ifndef un.InitHashAppModelId
7390    !verbose push
7391    !verbose ${_MOZFUNC_VERBOSE}
7392    !undef _MOZFUNC_UN
7393    !define _MOZFUNC_UN "un."
7394
7395    !insertmacro InitHashAppModelId
7396
7397    !undef _MOZFUNC_UN
7398    !define _MOZFUNC_UN
7399    !verbose pop
7400  !endif
7401!macroend
7402
7403################################################################################
7404# Helpers for taskbar progress
7405
7406!ifndef CLSCTX_INPROC_SERVER
7407  !define CLSCTX_INPROC_SERVER  1
7408!endif
7409
7410!define CLSID_ITaskbarList {56fdf344-fd6d-11d0-958a-006097c9a090}
7411!define IID_ITaskbarList3 {ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf}
7412!define ITaskbarList3->SetProgressValue $ITaskbarList3->9
7413!define ITaskbarList3->SetProgressState $ITaskbarList3->10
7414
7415/**
7416 * Creates a single uninitialized object of the ITaskbarList class with a
7417 * reference to the ITaskbarList3 interface. This object can be used to set
7418 * progress and state on the installer's taskbar icon using the helper macros
7419 * in this section.
7420 */
7421!macro ITBL3Create
7422
7423  !ifndef ${_MOZFUNC_UN}ITBL3Create
7424    Var ITaskbarList3
7425
7426    !verbose push
7427    !verbose ${_MOZFUNC_VERBOSE}
7428    !define ${_MOZFUNC_UN}ITBL3Create "!insertmacro ${_MOZFUNC_UN}ITBL3CreateCall"
7429
7430    Function ${_MOZFUNC_UN}ITBL3Create
7431      ; Setting to 0 allows the helper macros to detect when the object was not
7432      ; created.
7433      StrCpy $ITaskbarList3 0
7434      ; Don't create when running silently.
7435      ${Unless} ${Silent}
7436        ; This is only supported on Win 7 and above.
7437        ${If} ${AtLeastWin7}
7438          System::Call "ole32::CoCreateInstance(g '${CLSID_ITaskbarList}', \
7439                                                i 0, \
7440                                                i ${CLSCTX_INPROC_SERVER}, \
7441                                                g '${IID_ITaskbarList3}', \
7442                                                *i .s)"
7443          Pop $ITaskbarList3
7444        ${EndIf}
7445      ${EndUnless}
7446    FunctionEnd
7447
7448    !verbose pop
7449  !endif
7450!macroend
7451
7452!macro ITBL3CreateCall
7453  !verbose push
7454  !verbose ${_MOZFUNC_VERBOSE}
7455  Call ITBL3Create
7456  !verbose pop
7457!macroend
7458
7459!macro un.ITBL3CreateCall _PATH_TO_IMAGE
7460  !verbose push
7461  !verbose ${_MOZFUNC_VERBOSE}
7462  Call un.ITBL3Create
7463  !verbose pop
7464!macroend
7465
7466!macro un.ITBL3Create
7467  !ifndef un.ITBL3Create
7468    !verbose push
7469    !verbose ${_MOZFUNC_VERBOSE}
7470    !undef _MOZFUNC_UN
7471    !define _MOZFUNC_UN "un."
7472
7473    !insertmacro ITBL3Create
7474
7475    !undef _MOZFUNC_UN
7476    !define _MOZFUNC_UN
7477    !verbose pop
7478  !endif
7479!macroend
7480
7481/**
7482 * Sets the percentage completed on the taskbar process icon progress indicator.
7483 *
7484 * @param   _COMPLETED
7485 *          The proportion of the operation that has been completed in relation
7486 *          to _TOTAL.
7487 * @param   _TOTAL
7488 *          The value _COMPLETED will have when the operation has completed.
7489 *
7490 * $R8 = _COMPLETED
7491 * $R9 = _TOTAL
7492 */
7493!macro ITBL3SetProgressValueCall _COMPLETED _TOTAL
7494  Push ${_COMPLETED}
7495  Push ${_TOTAL}
7496  ${CallArtificialFunction} ITBL3SetProgressValue_
7497!macroend
7498
7499!define ITBL3SetProgressValue "!insertmacro ITBL3SetProgressValueCall"
7500!define un.ITBL3SetProgressValue "!insertmacro ITBL3SetProgressValueCall"
7501
7502!macro ITBL3SetProgressValue_
7503  Exch $R9
7504  Exch 1
7505  Exch $R8
7506  ${If} $ITaskbarList3 <> 0
7507    System::Call "${ITaskbarList3->SetProgressValue}(i$HWNDPARENT, l$R8, l$R9)"
7508  ${EndIf}
7509  Exch $R8
7510  Exch 1
7511  Exch $R9
7512!macroend
7513
7514; Normal state / no progress bar
7515!define TBPF_NOPROGRESS       0x00000000
7516; Marquee style progress bar
7517!define TBPF_INDETERMINATE    0x00000001
7518; Standard progress bar
7519!define TBPF_NORMAL           0x00000002
7520; Red taskbar button to indicate an error occurred
7521!define TBPF_ERROR            0x00000004
7522; Yellow taskbar button to indicate user attention (input) is required to
7523; resume progress
7524!define TBPF_PAUSED           0x00000008
7525
7526/**
7527 * Sets the state on the taskbar process icon progress indicator.
7528 *
7529 * @param   _STATE
7530 *          The state to set on the taskbar icon progress indicator. Only one of
7531 *          the states defined above should be specified.
7532 *
7533 * $R9 = _STATE
7534 */
7535!macro ITBL3SetProgressStateCall _STATE
7536  Push ${_STATE}
7537  ${CallArtificialFunction} ITBL3SetProgressState_
7538!macroend
7539
7540!define ITBL3SetProgressState "!insertmacro ITBL3SetProgressStateCall"
7541!define un.ITBL3SetProgressState "!insertmacro ITBL3SetProgressStateCall"
7542
7543!macro ITBL3SetProgressState_
7544  Exch $R9
7545  ${If} $ITaskbarList3 <> 0
7546    System::Call "${ITaskbarList3->SetProgressState}(i$HWNDPARENT, i$R9)"
7547  ${EndIf}
7548  Exch $R9
7549!macroend
7550
7551################################################################################
7552# Helpers for the new user interface
7553
7554!ifndef MAXDWORD
7555  !define MAXDWORD 0xffffffff
7556!endif
7557
7558!ifndef DT_WORDBREAK
7559  !define DT_WORDBREAK 0x0010
7560!endif
7561!ifndef DT_SINGLELINE
7562  !define DT_SINGLELINE 0x0020
7563!endif
7564!ifndef DT_NOCLIP
7565  !define DT_NOCLIP 0x0100
7566!endif
7567!ifndef DT_CALCRECT
7568  !define DT_CALCRECT 0x0400
7569!endif
7570!ifndef DT_EDITCONTROL
7571  !define DT_EDITCONTROL 0x2000
7572!endif
7573!ifndef DT_RTLREADING
7574  !define DT_RTLREADING 0x00020000
7575!endif
7576!ifndef DT_NOFULLWIDTHCHARBREAK
7577  !define DT_NOFULLWIDTHCHARBREAK 0x00080000
7578!endif
7579
7580!ifndef WS_EX_NOINHERITLAYOUT
7581  !define WS_EX_NOINHERITLAYOUT 0x00100000
7582!endif
7583!ifndef WS_EX_LAYOUTRTL
7584  !define WS_EX_LAYOUTRTL 0x00400000
7585!endif
7586
7587!ifndef PBS_MARQUEE
7588  !define PBS_MARQUEE 0x08
7589!endif
7590
7591!ifndef PBM_SETRANGE32
7592  !define PBM_SETRANGE32 0x406
7593!endif
7594!ifndef PBM_GETRANGE
7595  !define PBM_GETRANGE 0x407
7596!endif
7597
7598!ifndef SHACF_FILESYSTEM
7599  !define SHACF_FILESYSTEM 1
7600!endif
7601
7602!define MOZ_LOADTRANSPARENT ${LR_LOADFROMFILE}|${LR_LOADTRANSPARENT}|${LR_LOADMAP3DCOLORS}
7603
7604; Extend nsDialogs.nsh to support creating centered labels if it is already
7605; included
7606!ifmacrodef __NSD_DefineControl
7607!insertmacro __NSD_DefineControl LabelCenter
7608!define __NSD_LabelCenter_CLASS STATIC
7609!define __NSD_LabelCenter_STYLE ${DEFAULT_STYLES}|${SS_NOTIFY}|${SS_CENTER}
7610!define __NSD_LabelCenter_EXSTYLE ${WS_EX_TRANSPARENT}
7611!endif
7612
7613/**
7614 * Modified version of the __NSD_SetStretchedImage macro from nsDialogs.nsh that
7615 * supports transparency. See nsDialogs documentation for additional info.
7616 */
7617!macro __SetStretchedTransparentImage CONTROL IMAGE HANDLE
7618  Push $0
7619  Push $1
7620  Push $2
7621  Push $R0
7622
7623  StrCpy $R0 ${CONTROL} ; in case ${CONTROL} is $0
7624  StrCpy $1 ""
7625  StrCpy $2 ""
7626
7627  System::Call '*(i, i, i, i) i.s'
7628  Pop $0
7629
7630  ${If} $0 <> 0
7631    System::Call 'user32::GetClientRect(i R0, i r0)'
7632    System::Call '*$0(i, i, i .s, i .s)'
7633    System::Free $0
7634    Pop $1
7635    Pop $2
7636  ${EndIf}
7637
7638  System::Call 'user32::LoadImageW(i 0, t s, i ${IMAGE_BITMAP}, i r1, i r2, \
7639                                   i ${MOZ_LOADTRANSPARENT}) i .s' "${IMAGE}"
7640  Pop $0
7641  SendMessage $R0 ${STM_SETIMAGE} ${IMAGE_BITMAP} $0
7642
7643  SetCtlColors $R0 "" transparent
7644  ${NSD_AddExStyle} $R0 ${WS_EX_TRANSPARENT}|${WS_EX_TOPMOST}
7645
7646  Pop $R0
7647  Pop $2
7648  Pop $1
7649  Exch $0
7650  Pop ${HANDLE}
7651!macroend
7652!define SetStretchedTransparentImage "!insertmacro __SetStretchedTransparentImage"
7653
7654/**
7655 * Removes a single style from a control.
7656 *
7657 * _HANDLE the handle of the control
7658 * _STYLE  the style to remove
7659 */
7660!macro _RemoveStyle _HANDLE _STYLE
7661  Push $0
7662
7663  System::Call 'user32::GetWindowLongW(i ${_HANDLE}, i ${GWL_STYLE}) i .r0'
7664  IntOp $0 $0 | ${_STYLE}
7665  IntOp $0 $0 - ${_STYLE}
7666  System::Call 'user32::SetWindowLongW(i ${_HANDLE}, i ${GWL_STYLE}, i r0)'
7667
7668  Pop $0
7669!macroend
7670!define RemoveStyle "!insertmacro _RemoveStyle"
7671
7672/**
7673 * Removes a single extended style from a control.
7674 *
7675 * _HANDLE  the handle of the control
7676 * _EXSTYLE the extended style to remove
7677 */
7678!macro _RemoveExStyle _HANDLE _EXSTYLE
7679  Push $0
7680
7681  System::Call 'user32::GetWindowLongW(i ${_HANDLE}, i ${GWL_EXSTYLE}) i .r0'
7682  IntOp $0 $0 | ${_EXSTYLE}
7683  IntOp $0 $0 - ${_EXSTYLE}
7684  System::Call 'user32::SetWindowLongW(i ${_HANDLE}, i ${GWL_EXSTYLE}, i r0)'
7685
7686  Pop $0
7687!macroend
7688!define RemoveExStyle "!insertmacro _RemoveExStyle"
7689
7690/**
7691 * Gets the extent of the specified text in pixels for sizing a control.
7692 *
7693 * _TEXT       the text to get the text extent for
7694 * _FONT       the font to use when getting the text extent
7695 * _RES_WIDTH  return value - control width for the text
7696 * _RES_HEIGHT return value - control height for the text
7697 */
7698!macro GetTextExtentCall _TEXT _FONT _RES_WIDTH _RES_HEIGHT
7699  Push "${_TEXT}"
7700  Push "${_FONT}"
7701  ${CallArtificialFunction} GetTextExtent_
7702  Pop ${_RES_WIDTH}
7703  Pop ${_RES_HEIGHT}
7704!macroend
7705
7706!define GetTextExtent "!insertmacro GetTextExtentCall"
7707!define un.GetTextExtent "!insertmacro GetTextExtentCall"
7708
7709!macro GetTextExtent_
7710  Exch $0 ; font
7711  Exch 1
7712  Exch $1 ; text
7713  Push $2
7714  Push $3
7715  Push $4
7716  Push $5
7717  Push $6
7718  Push $7
7719
7720  ; Reuse the existing NSIS control which is used for BrandingText instead of
7721  ; creating a new control.
7722  GetDlgItem $2 $HWNDPARENT 1028
7723
7724  System::Call 'user32::GetDC(i r2) i .r3'
7725  System::Call 'gdi32::SelectObject(i r3, i r0)'
7726
7727  StrLen $4 "$1"
7728
7729  System::Call '*(i, i) i .r5'
7730  System::Call 'gdi32::GetTextExtentPoint32W(i r3, t$\"$1$\", i r4, i r5)'
7731  System::Call '*$5(i .r6, i .r7)'
7732  System::Free $5
7733
7734  System::Call 'user32::ReleaseDC(i r2, i r3)'
7735
7736  StrCpy $1 $7
7737  StrCpy $0 $6
7738
7739  Pop $7
7740  Pop $6
7741  Pop $5
7742  Pop $4
7743  Pop $3
7744  Pop $2
7745  Exch $1 ; return height
7746  Exch 1
7747  Exch $0 ; return width
7748!macroend
7749
7750/**
7751 * Gets the width and the height of a control in pixels.
7752 *
7753 * _HANDLE     the handle of the control
7754 * _RES_WIDTH  return value - control width for the text
7755 * _RES_HEIGHT return value - control height for the text
7756 */
7757!macro GetDlgItemWidthHeightCall _HANDLE _RES_WIDTH _RES_HEIGHT
7758  Push "${_HANDLE}"
7759  ${CallArtificialFunction} GetDlgItemWidthHeight_
7760  Pop ${_RES_WIDTH}
7761  Pop ${_RES_HEIGHT}
7762!macroend
7763
7764!define GetDlgItemWidthHeight "!insertmacro GetDlgItemWidthHeightCall"
7765!define un.GetDlgItemWidthHeight "!insertmacro GetDlgItemWidthHeightCall"
7766
7767!macro GetDlgItemWidthHeight_
7768  Exch $0 ; handle for the control
7769  Push $1
7770  Push $2
7771
7772  System::Call '*(i, i, i, i) i .r2'
7773  ; The left and top values will always be 0 so the right and bottom values
7774  ; will be the width and height.
7775  System::Call 'user32::GetClientRect(i r0, i r2)'
7776  System::Call '*$2(i, i, i .r0, i .r1)'
7777  System::Free $2
7778
7779  Pop $2
7780  Exch $1 ; return height
7781  Exch 1
7782  Exch $0 ; return width
7783!macroend
7784
7785/**
7786 * Gets the number of pixels from the beginning of the dialog to the end of a
7787 * control in a RTL friendly manner.
7788 *
7789 * _HANDLE the handle of the control
7790 * _RES_PX return value - pixels from the beginning of the dialog to the end of
7791 *         the control
7792 */
7793!macro GetDlgItemEndPXCall _HANDLE _RES_PX
7794  Push "${_HANDLE}"
7795  ${CallArtificialFunction} GetDlgItemEndPX_
7796  Pop ${_RES_PX}
7797!macroend
7798
7799!define GetDlgItemEndPX "!insertmacro GetDlgItemEndPXCall"
7800!define un.GetDlgItemEndPX "!insertmacro GetDlgItemEndPXCall"
7801
7802!macro GetDlgItemEndPX_
7803  Exch $0 ; handle of the control
7804  Push $1
7805  Push $2
7806
7807  ; #32770 is the dialog class
7808  FindWindow $1 "#32770" "" $HWNDPARENT
7809  System::Call '*(i, i, i, i) i .r2'
7810  System::Call 'user32::GetWindowRect(i r0, i r2)'
7811  System::Call 'user32::MapWindowPoints(i 0, i r1,i r2, i 2)'
7812  System::Call '*$2(i, i, i .r0, i)'
7813  System::Free $2
7814
7815  Pop $2
7816  Pop $1
7817  Exch $0 ; pixels from the beginning of the dialog to the end of the control
7818!macroend
7819
7820/**
7821 * Gets the width and height for sizing a control that has the specified text.
7822 * If the text has embedded newlines then the width and height will be
7823 * determined without trying to optimize the control's width and height. If the
7824 * text doesn't contain newlines the control's height and width will be
7825 * dynamically determined using a minimum of 3 lines (incrementing the
7826 * number of lines if necessary) for the height and the maximum width specified.
7827 *
7828 * _TEXT       the text
7829 * _FONT       the font to use when getting the width and height
7830 * _MAX_WIDTH  the maximum width for the control
7831 * _RES_WIDTH  return value - control width for the text
7832 * _RES_HEIGHT return value - control height for the text
7833 */
7834!macro GetTextWidthHeight
7835
7836  !ifndef ${_MOZFUNC_UN}GetTextWidthHeight
7837    !define _MOZFUNC_UN_TMP ${_MOZFUNC_UN}
7838    !insertmacro ${_MOZFUNC_UN_TMP}WordFind
7839    !undef _MOZFUNC_UN
7840    !define _MOZFUNC_UN ${_MOZFUNC_UN_TMP}
7841    !undef _MOZFUNC_UN_TMP
7842
7843    !verbose push
7844    !verbose ${_MOZFUNC_VERBOSE}
7845    !define ${_MOZFUNC_UN}GetTextWidthHeight "!insertmacro ${_MOZFUNC_UN}GetTextWidthHeightCall"
7846
7847    Function ${_MOZFUNC_UN}GetTextWidthHeight
7848      Exch $0  ; maximum width use to calculate the control's width and height
7849      Exch 1
7850      Exch $1  ; font
7851      Exch 2
7852      Exch $2  ; text
7853      Push $3
7854      Push $4
7855      Push $5
7856      Push $6
7857      Push $7
7858      Push $8
7859      Push $9
7860      Push $R0
7861      Push $R1
7862      Push $R2
7863
7864      StrCpy $R2 "${DT_NOCLIP}|${DT_CALCRECT}"
7865      !ifdef ${AB_CD}_rtl
7866        StrCpy $R2 "$R2|${DT_RTLREADING}"
7867      !endif
7868
7869      ; Reuse the existing NSIS control which is used for BrandingText instead
7870      ; of creating a new control.
7871      GetDlgItem $3 $HWNDPARENT 1028
7872
7873      System::Call 'user32::GetDC(i r3) i .r4'
7874      System::Call 'gdi32::SelectObject(i r4, i r1)'
7875
7876      StrLen $5 "$2" ; text length
7877      System::Call '*(i, i, i, i) i .r6'
7878
7879      ClearErrors
7880      ${${_MOZFUNC_UN}WordFind} "$2" "$\n" "E#" $R0
7881      ${If} ${Errors}
7882        ; When there aren't newlines in the text calculate the size of the
7883        ; rectangle needed for the text with a minimum of three lines of text.
7884        ClearErrors
7885        System::Call 'user32::DrawTextW(i r4, t $\"$2$\", i r5, i r6, \
7886                                        i $R2|${DT_SINGLELINE})'
7887        System::Call '*$6(i, i, i .r8, i .r7)'
7888        System::Free $6
7889
7890        ; Get the approximate number height needed to display the text starting
7891        ; with a minimum of 3 lines of text.
7892        StrCpy $9 $8
7893        StrCpy $R1 2 ; set the number of lines initially to 2
7894        ${Do}
7895          IntOp $R1 $R1 + 1 ; increment the number of lines
7896          IntOp $9 $8 / $R1
7897        ${LoopUntil} $9 < $0
7898        IntOp $7 $7 * $R1
7899
7900        StrCpy $R0 $9
7901        ${Do}
7902          IntOp $R0 $R0 + 20
7903          System::Call '*(i, i, i R0, i r7) i .r6'
7904          System::Call 'user32::DrawTextW(i r4, t $\"$2$\", i r5, i r6, \
7905                                          i $R2|${DT_WORDBREAK}) i .R1'
7906          System::Call '*$6(i, i, i .r8, i .r9)'
7907          System::Free $6
7908        ${LoopUntil} $7 >= $R1
7909      ${Else}
7910        ; When there are newlines in the text just return the size of the
7911        ; rectangle for the text.
7912        System::Call 'user32::DrawTextW(i r4, t $\"$2$\", i r5, i r6, i $R2)'
7913        System::Call '*$6(i, i, i .r8, i .r9)'
7914        System::Free $6
7915      ${EndIf}
7916
7917      ; Reselect the original DC
7918      System::Call 'gdi32::SelectObject(i r4, i r1)'
7919      System::Call 'user32::ReleaseDC(i r3, i r4)'
7920
7921      StrCpy $1 $9
7922      StrCpy $0 $8
7923
7924      Pop $R2
7925      Pop $R1
7926      Pop $R0
7927      Pop $9
7928      Pop $8
7929      Pop $7
7930      Pop $6
7931      Pop $5
7932      Pop $4
7933      Pop $3
7934      Exch $2
7935      Exch 2
7936      Exch $1 ; return height
7937      Exch 1
7938      Exch $0 ; return width
7939    FunctionEnd
7940
7941    !verbose pop
7942  !endif
7943!macroend
7944
7945!macro GetTextWidthHeightCall _TEXT _FONT _MAX_WIDTH _RES_WIDTH _RES_HEIGHT
7946  !verbose push
7947  !verbose ${_MOZFUNC_VERBOSE}
7948  Push "${_TEXT}"
7949  Push "${_FONT}"
7950  Push "${_MAX_WIDTH}"
7951  Call GetTextWidthHeight
7952  Pop ${_RES_WIDTH}
7953  Pop ${_RES_HEIGHT}
7954  !verbose pop
7955!macroend
7956
7957!macro un.GetTextWidthHeightCall _TEXT _FONT _MAX_WIDTH _RES_WIDTH _RES_HEIGHT
7958  !verbose push
7959  !verbose ${_MOZFUNC_VERBOSE}
7960  Push "${_TEXT}"
7961  Push "${_FONT}"
7962  Push "${_MAX_WIDTH}"
7963  Call un.GetTextWidthHeight
7964  Pop ${_RES_WIDTH}
7965  Pop ${_RES_HEIGHT}
7966  !verbose pop
7967!macroend
7968
7969!macro un.GetTextWidthHeight
7970  !ifndef un.GetTextWidthHeight
7971    !verbose push
7972    !verbose ${_MOZFUNC_VERBOSE}
7973    !undef _MOZFUNC_UN
7974    !define _MOZFUNC_UN "un."
7975
7976    !insertmacro GetTextWidthHeight
7977
7978    !undef _MOZFUNC_UN
7979    !define _MOZFUNC_UN
7980    !verbose pop
7981  !endif
7982!macroend
7983
7984/**
7985 * Gets the elapsed time in seconds between two values in milliseconds stored as
7986 * an int64. The caller will typically get the millisecond values using
7987 * GetTickCount with a long return value as follows.
7988 * System::Call "kernel32::GetTickCount()l .s"
7989 * Pop $varname
7990 *
7991 * _START_TICK_COUNT
7992 * _FINISH_TICK_COUNT
7993 * _RES_ELAPSED_SECONDS return value - elapsed time between _START_TICK_COUNT
7994 *                      and _FINISH_TICK_COUNT in seconds.
7995 */
7996!macro GetSecondsElapsedCall _START_TICK_COUNT _FINISH_TICK_COUNT _RES_ELAPSED_SECONDS
7997  Push "${_START_TICK_COUNT}"
7998  Push "${_FINISH_TICK_COUNT}"
7999  ${CallArtificialFunction} GetSecondsElapsed_
8000  Pop ${_RES_ELAPSED_SECONDS}
8001!macroend
8002
8003!define GetSecondsElapsed "!insertmacro GetSecondsElapsedCall"
8004!define un.GetSecondsElapsed "!insertmacro GetSecondsElapsedCall"
8005
8006!macro GetSecondsElapsed_
8007  Exch $0 ; finish tick count
8008  Exch 1
8009  Exch $1 ; start tick count
8010
8011  System::Int64Op $0 - $1
8012  Pop $0
8013  ; Discard the top bits of the int64 by bitmasking with MAXDWORD
8014  System::Int64Op $0 & ${MAXDWORD}
8015  Pop $0
8016
8017  ; Convert from milliseconds to seconds
8018  System::Int64Op $0 / 1000
8019  Pop $0
8020
8021  Pop $1
8022  Exch $0 ; return elapsed seconds
8023!macroend
8024
8025