Bug 453797 - Port Bug 392303 (Simplify installer changes) to SeaMonkey installer, r=Neil, blocking2.0a2=IanN
authorFrank Wein <mcsmurf@mcsmurf.de>
Mon, 01 Dec 2008 09:17:21 +0100
changeset 1265 963289aacfa31ded39683c31fe0e6959bd2e77b6
parent 1264 ba6cc9834591a247a834adb4dfdf62b399671ad7
child 1266 28df2a677d26241f6cdf6db03b60b4fd42ab4baf
push idunknown
push userunknown
push dateunknown
reviewersNeil
bugs453797, 392303
Bug 453797 - Port Bug 392303 (Simplify installer changes) to SeaMonkey installer, r=Neil, blocking2.0a2=IanN
suite/installer/windows/nsis/custom.nsi
suite/installer/windows/nsis/defines.nsi.in
suite/installer/windows/nsis/installer.nsi
suite/installer/windows/nsis/shared.nsh
suite/installer/windows/nsis/uninstaller.nsi
suite/locales/en-US/installer/windows/custom.properties
--- a/suite/installer/windows/nsis/custom.nsi
+++ b/suite/installer/windows/nsis/custom.nsi
@@ -71,104 +71,104 @@
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Bottom "$R3"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" State  "1"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Flags  "GROUP"
     ${GetSize} "$EXEDIR\optional\extensions\{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}" "/S=0K" $0 $8 $9
     ${If} ${FileExists} "$EXEDIR\optional\extensions\langpack-${AB_CD}@chatzilla.mozilla.org"
       ${GetSize} "$EXEDIR\optional\extensions\langpack-${AB_CD}@chatzilla.mozilla.org" "/S=0K" $1 $8 $9
       IntOp $0 $0 + $1
     ${EndIf}
-    SectionSetSize 1 $0
+    SectionSetSize ${CZ_IDX} $0
     IntOp $R1 $R1 + 1
     IntOp $R2 $R2 + $R4
     IntOp $R3 $R3 + $R4
   ${Else}
     ; Hide ChatZilla in the components page if it isn't available.
-    SectionSetText 1 ""
+    SectionSetText ${CZ_IDX} ""
   ${EndIf}
 
   ${If} ${FileExists} "$EXEDIR\optional\extensions\inspector@mozilla.org"
     ; Set the details for DOMI
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Type   "checkbox"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Text   "$(DOMI_TITLE)"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Left   "15"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Right  "-1"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Top    "$R2"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Bottom "$R3"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" State  "1"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Flags  "GROUP"
     ${GetSize} "$EXEDIR\optional\extensions\inspector@mozilla.org" "/S=0K" $0 $8 $9
-    SectionSetSize 2 $0
+    SectionSetSize ${DOMI_IDX} $0
     IntOp $R1 $R1 + 1
     IntOp $R2 $R2 + $R4
     IntOp $R3 $R3 + $R4
   ${Else}
     ; Hide DOMi in the components page if it isn't available.
-    SectionSetText 2 ""
+    SectionSetText ${DOMI_IDX} ""
   ${EndIf}
 
   ${If} ${FileExists} "$EXEDIR\optional\extensions\debugQA@mozilla.org"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Type   "checkbox"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Text   "$(DEBUGQA_TITLE)"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Left   "15"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Right  "-1"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Top    "$R2"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Bottom "$R3"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" State  "1"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Flags  "GROUP"
     ${GetSize} "$EXEDIR\optional\extensions\debugQA@mozilla.org" "/S=0K" $0 $8 $9
-    SectionSetSize 3 $0
+    SectionSetSize ${DEBUG_IDX} $0
     IntOp $R1 $R1 + 1
     IntOp $R2 $R2 + $R4
     IntOp $R3 $R3 + $R4
   ${Else}
     ; Hide debugQA in the components page if it isn't available.
-    SectionSetText 3 ""
+    SectionSetText ${DEBUG_IDX} ""
   ${EndIf}
 
   ${If} ${FileExists} "$EXEDIR\optional\extensions\p@m"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Type   "checkbox"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Text   "$(PALMSYNC_TITLE)"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Left   "15"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Right  "-1"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Top    "$R2"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Bottom "$R3"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" State  "1"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Flags  "GROUP"
     ${GetSize} "$EXEDIR\optional\extensions\p@m" "/S=0K" $0 $8 $9
-    SectionSetSize 4 $0
+    SectionSetSize ${PALM_IDX} $0
     IntOp $R1 $R1 + 1
     IntOp $R2 $R2 + $R4
     IntOp $R3 $R3 + $R4
   ${Else}
     ; Hide Palm Sync in the components page if it isn't available.
-    SectionSetText 4 ""
+    SectionSetText ${PALM_IDX} ""
   ${EndIf}
 
   ${If} ${FileExists} "$EXEDIR\optional\extensions\{f13b157f-b174-47e7-a34d-4815ddfdfeb8}"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Type   "checkbox"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Text   "$(VENKMAN_TITLE)"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Left   "15"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Right  "-1"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Top    "$R2"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Bottom "$R3"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" State  "1"
     WriteINIStr "$PLUGINSDIR\components.ini" "Field $R1" Flags  "GROUP"
     ${GetSize} "$EXEDIR\optional\extensions\{f13b157f-b174-47e7-a34d-4815ddfdfeb8}" "/S=0K" $0 $8 $9
     ${If} ${FileExists} "$EXEDIR\optional\extensions\langpack-${AB_CD}@venkman.mozilla.org"
       ${GetSize} "$EXEDIR\optional\extensions\langpack-${AB_CD}@venkman.mozilla.org" "/S=0K" $1 $8 $9
       IntOp $0 $0 + $1
     ${EndIf}
-    SectionSetSize 5 $0
+    SectionSetSize ${VENKMAN_IDX} $0
     IntOp $R1 $R1 + 1
     IntOp $R2 $R2 + $R4
     IntOp $R3 $R3 + $R4
   ${Else}
     ; Hide Venkman in the components page if it isn't available.
-    SectionSetText 5 ""
+    SectionSetText ${VENKMAN_IDX} ""
   ${EndIf}
 
   ; Set new values for the top and bottom of labels
   ; Top of label box
   StrCpy $R2 27
   ; Bottom of label box
   StrCpy $R3 47
 
--- a/suite/installer/windows/nsis/defines.nsi.in
+++ b/suite/installer/windows/nsis/defines.nsi.in
@@ -10,8 +10,9 @@
 !define FileMainEXE           "@MOZ_APP_NAME@.exe"
 !define WindowClass           "SeaMonkeyMessageWindow"
 !define DDEApplication        "SeaMonkey"
 
 !define AppRegName            "SeaMonkey"
 !define AppRegNameMail        "SeaMonkey (Mail)"
 !define AppRegNameNews        "SeaMonkey (News)"
 
+!define MinSupportedVer       "Microsoft Windows 2000"
--- a/suite/installer/windows/nsis/installer.nsi
+++ b/suite/installer/windows/nsis/installer.nsi
@@ -31,96 +31,115 @@
 # decision by deleting the provisions above and replace them with the notice
 # and other provisions required by the GPL or the LGPL. If you do not delete
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK *****
 
 # Also requires:
+# AppAssocReg http://nsis.sourceforge.net/Application_Association_Registration_plug-in
 # ShellLink plugin http://nsis.sourceforge.net/ShellLink_plug-in
+# UAC         http://nsis.sourceforge.net/UAC_plug-in
 
 ; Set verbosity to 3 (e.g. no script) to lessen the noise in the build logs
 !verbose 3
 
 ; 7-Zip provides better compression than the lzma from NSIS so we add the files
 ; uncompressed and use 7-Zip to create a SFX archive of it
 SetDatablockOptimize on
 SetCompress off
 CRCCheck on
 
+RequestExecutionLevel user
+
 !addplugindir ./
 
 ; empty files - except for the comment line - for generating custom pages.
 !system 'echo ; > options.ini'
 !system 'echo ; > components.ini'
 !system 'echo ; > shortcuts.ini'
 !system 'echo ; > summary.ini'
 
+; USE_UAC_PLUGIN is temporary until other apps have been updated to use the UAC plugin
+!define USE_UAC_PLUGIN
+
 Var TmpVal
 Var StartMenuDir
 Var InstallType
 Var AddStartMenuSC
 Var AddQuickLaunchSC
 Var AddDesktopSC
-Var fhInstallLog
-Var fhUninstallLog
 
 ; Other included files may depend upon these includes!
 ; The following includes are provided by NSIS.
 !include FileFunc.nsh
 !include LogicLib.nsh
 !include TextFunc.nsh
 !include WinMessages.nsh
+!include WinVer.nsh
 !include WordFunc.nsh
 !include MUI.nsh
 
-!insertmacro FileJoin
-!insertmacro GetTime
-!insertmacro LineFind
 !insertmacro StrFilter
 !insertmacro TrimNewLines
-!insertmacro WordFind
-!insertmacro WordReplace
-!insertmacro GetSize
+!insertmacro GetOptions
 !insertmacro GetParameters
-!insertmacro GetOptions
-!insertmacro GetRoot
-!insertmacro DriveSpace
-!insertmacro GetParent
+!insertmacro GetSize
+!insertmacro WordFind
 
 ; NSIS provided macros that we have overridden
 !include overrides.nsh
 !insertmacro LocateNoDetails
 !insertmacro TextCompareNoDetails
 
 ; The following includes are custom.
 !include branding.nsi
 !include defines.nsi
 !include common.nsh
 !include locales.nsi
 !include version.nsh
 !include custom.nsi
 
 VIAddVersionKey "FileDescription" "${BrandShortName} Installer"
+VIAddVersionKey "OrginalFilename" "setup.exe"
 
-!insertmacro GetLongPath
+; Must be inserted before other macros that use logging
+!insertmacro _LoggingCommon
+
+!insertmacro AddDDEHandlerValues
+!insertmacro AddHandlerValues
+!insertmacro ChangeMUIHeaderImage
+!insertmacro CheckForFilesInUse
+!insertmacro CleanUpdatesDir
+!insertmacro CloseApp
+!insertmacro CreateRegKey
+!insertmacro CopyFilesFromDir
+!insertmacro GetPathFromString
+!insertmacro GetParent
+!insertmacro IsHandlerForInstallDir
+!insertmacro ManualCloseAppPrompt
 !insertmacro RegCleanMain
 !insertmacro RegCleanUninstall
-!insertmacro CloseApp
+!insertmacro CreateRegKey
+!insertmacro UnloadUAC
 !insertmacro WriteRegStr2
 !insertmacro WriteRegDWORD2
-!insertmacro CreateRegKey
-!insertmacro CanWriteToInstallDir
-!insertmacro CheckDiskSpace
-!insertmacro GetPathFromString
-!insertmacro AddHandlerValues
 
 !include shared.nsh
 
+; Helper macros for ui callbacks. Insert these after shared.nsh
+!insertmacro CheckCustomCommon
+!insertmacro InstallEndCleanupCommon
+!insertmacro InstallOnInitCommon
+!insertmacro InstallStartCleanupCommon
+!insertmacro LeaveDirectoryCommon
+!insertmacro OnEndCommon
+!insertmacro PreDirectoryCommon
+
 Name "${BrandFullName}"
 OutFile "setup.exe"
 InstallDirRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal} (${AppVersion})" "InstallLocation"
 InstallDir "$PROGRAMFILES\${BrandFullName}\"
 ShowInstDetails nevershow
 
 ReserveFile options.ini
 ReserveFile components.ini
@@ -144,19 +163,21 @@ ReserveFile summary.ini
 !else
 !define MUI_HEADERIMAGE_BITMAP wizHeader.bmp
 !endif
 
 /**
  * Installation Pages
  */
 ; Welcome Page
+!define MUI_PAGE_CUSTOMFUNCTION_PRE preWelcome
 !insertmacro MUI_PAGE_WELCOME
 
 ; License Page
+!define MUI_PAGE_CUSTOMFUNCTION_SHOW showLicense
 !define MUI_LICENSEPAGE_CHECKBOX
 !insertmacro MUI_PAGE_LICENSE license.txt
 
 ; Custom Options Page
 Page custom preOptions leaveOptions
 
 ; Custom Components Page
 Page custom preComponents leaveComponents
@@ -167,108 +188,65 @@ Page custom preComponents leaveComponent
 !define MUI_DIRECTORYPAGE_VERIFYONLEAVE
 !insertmacro MUI_PAGE_DIRECTORY
 
 ; Custom Shortcuts Page
 Page custom preShortcuts leaveShortcuts
 
 ; Start Menu Folder Page Configuration
 !define MUI_PAGE_CUSTOMFUNCTION_PRE preStartMenu
+!define MUI_PAGE_CUSTOMFUNCTION_LEAVE leaveStartMenu
 !define MUI_STARTMENUPAGE_NODISABLE
 !define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKLM"
 !define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\Mozilla\${BrandFullNameInternal}\${AppVersion} (${AB_CD})\Main"
 !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder"
 !insertmacro MUI_PAGE_STARTMENU Application $StartMenuDir
 
 ; Custom Summary Page
-Page custom preSummary
+Page custom preSummary leaveSummary
 
 ; Install Files Page
-!define MUI_PAGE_CUSTOMFUNCTION_LEAVE leaveInstFiles
 !insertmacro MUI_PAGE_INSTFILES
 
 ; Finish Page
-!define MUI_FINISHPAGE_NOREBOOTSUPPORT
 !define MUI_FINISHPAGE_TITLE_3LINES
 !define MUI_FINISHPAGE_RUN
 !define MUI_FINISHPAGE_RUN_FUNCTION LaunchApp
 !define MUI_FINISHPAGE_RUN_TEXT $(LAUNCH_TEXT)
 !define MUI_PAGE_CUSTOMFUNCTION_PRE preFinish
 !insertmacro MUI_PAGE_FINISH
 
-################################################################################
-# Install Sections
+; Use the default dialog for IDD_VERIFY for a simple Banner
+ChangeUI IDD_VERIFY "${NSISDIR}\Contrib\UIs\default.exe"
 
-Section "-Application" Section1
-  SectionIn 1 RO
-  SetDetailsPrint textonly
+################################################################################
+
+; Cleanup operations to perform at the start of the installation.
+Section "-InstallStartCleanup"
+  SetDetailsPrint both
   DetailPrint $(STATUS_CLEANUP)
   SetDetailsPrint none
 
-  ; Try to delete the app's main executable and if we can't delete it try to
-  ; close the app. This allows running an instance that is located in another
-  ; directory and prevents the launching of the app during the installation.
-  ; A copy of the executable is placed in a temporary directory so it can be
-  ; copied back in the case where a specific file is checked / found to be in
-  ; use that would prevent a successful install.
+  SetOutPath "$INSTDIR"
+  ${StartInstallLog} "${BrandFullName}" "${AB_CD}" "${AppVersion}" "${GREVersion}"
 
-  ; Create a temporary backup directory
-  GetTempFileName $TmpVal "$TEMP"
-  ${DeleteFile} $TmpVal
-  SetOutPath $TmpVal
-
-  ${If} ${FileExists} "$INSTDIR\${FileMainEXE}"
+  ; Delete the app exe to prevent launching the app while we are installing.
+  ClearErrors
+  ${DeleteFile} "$INSTDIR\${FileMainEXE}"
+  ${If} ${Errors}
+    ; If the user closed the application it can take several seconds for it to
+    ; shut down completely. If the application is being used by another user we
+    ; can rename the file and then delete is when the system is restarted.
+    Sleep 5000
+    ${DeleteFile} "$INSTDIR\${FileMainEXE}"
     ClearErrors
-    CopyFiles /SILENT "$INSTDIR\${FileMainEXE}" "$TmpVal\${FileMainEXE}"
-    Delete "$INSTDIR\${FileMainEXE}"
-    ${If} ${Errors}
-      ClearErrors
-      ${CloseApp} "true" $(WARN_APP_RUNNING_INSTALL)
-      ; Try to delete it again to prevent launching the app while we are
-      ; installing.
-      ClearErrors
-      CopyFiles /SILENT "$INSTDIR\${FileMainEXE}" "$TmpVal\${FileMainEXE}"
-      Delete "$INSTDIR\${FileMainEXE}"
-      ${If} ${Errors}
-        ClearErrors
-        ; Try closing the app a second time
-        ${CloseApp} "true" $(WARN_APP_RUNNING_INSTALL)
-        StrCpy $R1 "${FileMainEXE}"
-        Call CheckInUse
-      ${EndIf}
-    ${EndIf}
   ${EndIf}
 
-  StrCpy $R1 "freebl3.dll"
-  Call CheckInUse
-
-  StrCpy $R1 "nssckbi.dll"
-  Call CheckInUse
-
-  StrCpy $R1 "nspr4.dll"
-  Call CheckInUse
-
-  StrCpy $R1 "xpicleanup.exe"
-  Call CheckInUse
-
-  SetOutPath $INSTDIR
-  RmDir /r "$TmpVal"
-  ClearErrors
-
-  ; During an install Vista checks if a new entry is added under the uninstall
-  ; registry key (e.g. ARP). When the same version of the app is installed on
-  ; top of an existing install the key is deleted / added and the Program
-  ; Compatibility Assistant doesn't see this as a new entry and displays an
-  ; error to the user. See Bug 354000.
-  StrCpy $0 "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal} (${AppVersion})"
-  DeleteRegKey HKLM "$0"
-
-  ; Custom installs.
-  ${If} $InstallType != 1
-
+  ${If} $InstallType == ${INSTALLTYPE_CUSTOM}
+    ; Custom installs.
     ; If ChatZilla is installed and this install includes ChatZilla remove it
     ; from the installation directory. This will remove it if the user
     ; deselected ChatZilla on the components page.
     ${If} ${FileExists} "$INSTDIR\extensions\{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}"
     ${AndIf} ${FileExists} "$EXEDIR\optional\extensions\{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}"
       RmDir /r "$INSTDIR\extensions\{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}"
     ${EndIf}
     ${If} ${FileExists} "$INSTDIR\extensions\langpack-${AB_CD}@chatzilla.mozilla.org"
@@ -308,74 +286,34 @@ Section "-Application" Section1
       RmDir /r "$INSTDIR\extensions\{f13b157f-b174-47e7-a34d-4815ddfdfeb8}"
     ${EndIf}
     ${If} ${FileExists} "$INSTDIR\extensions\langpack-${AB_CD}@venkman.mozilla.org"
     ${AndIf} ${FileExists} "$EXEDIR\optional\extensions\langpack-${AB_CD}@venkman.mozilla.org"
       RmDir /r "$INSTDIR\extensions\langpack-${AB_CD}@venkman.mozilla.org"
     ${EndIf}
   ${EndIf}
 
-  Call CleanupOldLogs
-
-  ${If} ${FileExists} "$INSTDIR\uninstall\uninstall.log"
-    ; Diff cleanup.log with uninstall.bak
-    ${LogHeader} "Updating Uninstall Log With XPInstall Wizard Logs"
-    StrCpy $R0 "$INSTDIR\uninstall\uninstall.log"
-    StrCpy $R1 "$INSTDIR\uninstall\cleanup.log"
-    GetTempFileName $R2
-    FileOpen $R3 $R2 w
-    ${TextCompareNoDetails} "$R1" "$R0" "SlowDiff" "GetDiff"
-    FileClose $R3
-
-    ${Unless} ${Errors}
-      ${FileJoin} "$INSTDIR\uninstall\uninstall.log" "$R2" "$INSTDIR\uninstall\uninstall.log"
-    ${EndUnless}
-    ${DeleteFile} "$INSTDIR\uninstall\cleanup.log"
-    ${DeleteFile} "$R2"
-    ${DeleteFile} "$INSTDIR\uninstall\uninstall.bak"
-    Rename "$INSTDIR\uninstall\uninstall.log" "$INSTDIR\uninstall\uninstall.bak"
-  ${EndIf}
-
-  ${Unless} ${FileExists} "$INSTDIR\uninstall"
-    CreateDirectory "$INSTDIR\uninstall"
-  ${EndUnless}
+  ; Remove the updates directory for Vista and above
+  ${CleanUpdatesDir} "Mozilla\SeaMonkey"
 
-  FileOpen $fhUninstallLog "$INSTDIR\uninstall\uninstall.log" w
-  FileOpen $fhInstallLog "$INSTDIR\install.log" w
-
-  ${GetTime} "" "L" $0 $1 $2 $3 $4 $5 $6
-  FileWrite $fhInstallLog "${BrandFullName} Installation Started: $2-$1-$0 $4:$5:$6"
-  Call WriteLogSeparator
-
-  ${LogHeader} "Installation Details"
-  ${LogMsg} "Install Dir: $INSTDIR"
-  ${LogMsg} "Locale     : ${AB_CD}"
-  ${LogMsg} "App Version: ${AppVersion}"
-  ${LogMsg} "GRE Version: ${GREVersion}"
+  ${InstallStartCleanupCommon}
+SectionEnd
 
-  ${If} ${FileExists} "$EXEDIR\removed-files.log"
-    ${LogHeader} "Removing Obsolete Files and Directories"
-    ${LineFind} "$EXEDIR\removed-files.log" "/NUL" "1:-1" "onInstallDeleteFile"
-    ${LineFind} "$EXEDIR\removed-files.log" "/NUL" "1:-1" "onInstallRemoveDir"
-  ${EndIf}
+Section "-Application" APP_IDX
+  ${StartUninstallLog}
 
-  ${DeleteFile} "$INSTDIR\install_wizard.log"
-  ${DeleteFile} "$INSTDIR\install_status.log"
-
-  RmDir /r "$INSTDIR\updates"
-  ${DeleteFile} "$INSTDIR\updates.xml"
-  ${DeleteFile} "$INSTDIR\active-update.xml"
-
-  SetDetailsPrint textonly
+  SetDetailsPrint both 
   DetailPrint $(STATUS_INSTALL_APP)
   SetDetailsPrint none
+
   ${LogHeader} "Installing Main Files"
-  StrCpy $R0 "$EXEDIR\nonlocalized"
-  StrCpy $R1 "$INSTDIR"
-  Call DoCopyFiles
+  ${CopyFilesFromDir} "$EXEDIR\nonlocalized" "$INSTDIR" \
+                      "$(ERROR_CREATE_DIRECTORY_PREFIX)" \
+                      "$(ERROR_CREATE_DIRECTORY_SUFFIX)"
+
 
   ; Register DLLs
   ; XXXrstrong - AccessibleMarshal.dll can be used by multiple applications but
   ; is only registered for the last application installed. When the last
   ; application installed is uninstalled AccessibleMarshal.dll will no longer be
   ; registered. bug 338878
   ${LogHeader} "DLL Registration"
   ClearErrors
@@ -395,29 +333,24 @@ Section "-Application" Section1
   ${LogUninstall} "File: \components\xpti.dat"
   ${LogUninstall} "File: \.autoreg"
   ${LogUninstall} "File: \active-update.xml"
   ${LogUninstall} "File: \install.log"
   ${LogUninstall} "File: \install_status.log"
   ${LogUninstall} "File: \install_wizard.log"
   ${LogUninstall} "File: \updates.xml"
 
-  SetDetailsPrint textonly
+  SetDetailsPrint both
   DetailPrint $(STATUS_INSTALL_LANG)
   SetDetailsPrint none
+
   ${LogHeader} "Installing Localized Files"
-  StrCpy $R0 "$EXEDIR\localized"
-  StrCpy $R1 "$INSTDIR"
-  Call DoCopyFiles
-
-  ${If} $InstallType != 4
-    Call installChatZilla
-    Call installInspector
-    Call installVenkman
-  ${EndIf}
+  ${CopyFilesFromDir} "$EXEDIR\localized" "$INSTDIR" \
+                      "$(ERROR_CREATE_DIRECTORY_PREFIX)" \
+                      "$(ERROR_CREATE_DIRECTORY_SUFFIX)"
 
   ${LogHeader} "Adding Additional Files"
   ; Check if QuickTime is installed and copy the nsIQTScriptablePlugin.xpt from 
   ; directory into the app's components directory.
   ClearErrors
   ReadRegStr $R0 HKLM "Software\Apple Computer, Inc.\QuickTime" "InstallDir"
   ${Unless} ${Errors}
     Push $R0
@@ -450,56 +383,65 @@ Section "-Application" Section1
     StrCpy $AddQuickLaunchSC "1"
   ${EndIf}
 
   ; Default for creating Desktop shortcut (1 = create, 0 = don't create)
   ${If} $AddDesktopSC == ""
     StrCpy $AddDesktopSC "1"
   ${EndIf}
 
-  ; Remove registry entries for non-existent apps and for apps that point to our
-  ; install location in the Software\Mozilla key and uninstall registry entries
-  ; that point to our install location for both HKCU and HKLM.
+  ${LogHeader} "Adding Registry Entries"
   SetShellVarContext current  ; Set SHCTX to HKCU
   ${RegCleanMain} "Software\Mozilla"
   ${RegCleanUninstall}
-
-  SetShellVarContext all  ; Set SHCTX to HKLM
-  ${RegCleanMain} "Software\Mozilla"
-  ${RegCleanUninstall}
+  ${UpdateProtocolHandlers}
 
-  ${LogHeader} "Adding Registry Entries"
   ClearErrors
-  WriteRegStr HKLM "Software\Mozilla\InstallerTest" "InstallerTest" "Test"
+  WriteRegStr HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" "Write Test"
   ${If} ${Errors}
-    SetShellVarContext current  ; Set SHCTX to HKCU
     StrCpy $TmpVal "HKCU" ; used primarily for logging
   ${Else}
     SetShellVarContext all  ; Set SHCTX to HKLM
-    DeleteRegKey HKLM "Software\Mozilla\InstallerTest"
+    DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest"
     StrCpy $TmpVal "HKLM" ; used primarily for logging
+    ${RegCleanMain} "Software\Mozilla"
+    ${RegCleanUninstall}
+    ${UpdateProtocolHandlers}
   ${EndIf}
 
-  ; The previous installer adds several regsitry values to both HKLM and HKCU.
+  ; The previous installer adds several registry values to both HKLM and HKCU.
   ; We now try to add to HKLM and if that fails to HKCU
 
   ; The order that reg keys and values are added is important if you use the
   ; uninstall log to remove them on uninstall. When using the uninstall log you
   ; MUST add children first so they will be removed first on uninstall so they
   ; will be empty when the key is deleted. This allows the uninstaller to
   ; specify that only empty keys will be deleted.
   ${SetAppKeys}
 
   ; XXXrstrong - this should be set in shared.nsh along with "Create Quick
   ; Launch Shortcut" and Create Desktop Shortcut.
   StrCpy $0 "Software\Mozilla\${BrandFullNameInternal}\${AppVersion} (${AB_CD})\Uninstall"
   ${WriteRegDWORD2} $TmpVal "$0" "Create Start Menu Shortcut" $AddStartMenuSC 0
 
   ${FixClassKeys}
 
+  StrCpy $1 "$\"$8$\" -requestPending -osint -url $\"%1$\""
+  StrCpy $2 "$\"%1$\",,0,0,,,," 
+  ${GetLongPath} "$INSTDIR\${FileMainEXE}" $8 
+
+  ${AddDDEHandlerValues} "SeaMonkeyHTML" "$1" \
+                         "$INSTDIR\chrome\icons\default\html-file.ico" \
+                         "${AppRegName} Document" "" "${DDEApplication}" "$3" \
+                         "WWW_OpenURL"
+  ${AddDDEHandlerValues} "SeaMonkeyURL" "$1" "$8,0" "${AppRegName} URL" "" \
+                         "${DDEApplication}" "$2" "WWW_OpenURL"
+
+  ${FixShellIconHandler}
+
   ; The following keys should only be set if we can write to HKLM
   ${If} $TmpVal == "HKLM"
     ; Uninstall keys can only exist under HKLM on some versions of windows.
     ${SetUninstallKeys}
 
     ; Set the Start Menu Internet and Vista Registered App HKLM registry keys.
     ${SetStartMenuInternet}
     ${SetClientsMail}
@@ -530,392 +472,237 @@ Section "-Application" Section1
   StrCpy $0 "Software\Microsoft\MediaPlayer\ShimInclusionList\$R9"
   ${CreateRegKey} "$TmpVal" "$0" 0
 
   !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
 
   ; Create Start Menu shortcuts
   ${LogHeader} "Adding Shortcuts"
   ${If} $AddStartMenuSC == 1
-    CreateDirectory "$SMPROGRAMS\$StartMenuDir"
+    ${Unless} ${FileExists} "$SMPROGRAMS\$StartMenuDir"
+      CreateDirectory "$SMPROGRAMS\$StartMenuDir"
+      ${LogMsg} "Added Start Menu Directory: $SMPROGRAMS\$StartMenuDir"
+    ${EndUnless}
     CreateShortCut "$SMPROGRAMS\$StartMenuDir\${BrandFullNameInternal}.lnk" "$INSTDIR\${FileMainEXE}" "" "$INSTDIR\${FileMainEXE}" 0
     ${LogUninstall} "File: $SMPROGRAMS\$StartMenuDir\${BrandFullNameInternal}.lnk"
+    ${LogMsg} "Added Shortcut: $SMPROGRAMS\$StartMenuDir\${BrandFullNameInternal}.lnk"
     CreateShortCut "$SMPROGRAMS\$StartMenuDir\${BrandFullNameInternal} ($(SAFE_MODE)).lnk" "$INSTDIR\${FileMainEXE}" "-safe-mode" "$INSTDIR\${FileMainEXE}" 0
     ${LogUninstall} "File: $SMPROGRAMS\$StartMenuDir\${BrandFullNameInternal} ($(SAFE_MODE)).lnk"
+    ${LogMsg} "Added Shortcut: $SMPROGRAMS\$StartMenuDir${BrandFullNameInternal} ($(SAFE_MODE)).lnk"
     CreateShortCut "$SMPROGRAMS\$StartMenuDir\${BrandFullNameInternal} $(MAILNEWS_TEXT).lnk" "$INSTDIR\${FileMainEXE}" "-mail" "$INSTDIR\${FileMainEXE}" 0
     ${LogUninstall} "File: $SMPROGRAMS\$StartMenuDir\${BrandFullNameInternal} $(MAILNEWS_TEXT).lnk"
+    ${LogMsg} "Added Shortcut: $SMPROGRAMS\$StartMenuDir\${BrandFullNameInternal} $(MAILNEWS_TEXT).lnk"
     CreateShortCut "$SMPROGRAMS\$StartMenuDir\$(PROFILE_TEXT).lnk" "$INSTDIR\${FileMainEXE}" "-profileManager" "$INSTDIR\${FileMainEXE}" 0
     ${LogUninstall} "File: $SMPROGRAMS\$StartMenuDir\$(PROFILE_TEXT).lnk"
+    ${LogMsg} "Added Shortcut: $SMPROGRAMS\$StartMenuDir\$(PROFILE_TEXT).lnk"
   ${EndIf}
 
   ; perhaps use the uninstall keys
   ${If} $AddQuickLaunchSC == 1
     CreateShortCut "$QUICKLAUNCH\${BrandFullName}.lnk" "$INSTDIR\${FileMainEXE}" "" "$INSTDIR\${FileMainEXE}" 0
     ${LogUninstall} "File: $QUICKLAUNCH\${BrandFullName}.lnk"
+    ${LogMsg} "Added Shortcut: $QUICKLAUNCH\${BrandFullName}.lnk"
   ${EndIf}
 
-  ${LogHeader} "Updating Quick Launch Shortcuts"
   ${If} $AddDesktopSC == 1
     CreateShortCut "$DESKTOP\${BrandFullName}.lnk" "$INSTDIR\${FileMainEXE}" "" "$INSTDIR\${FileMainEXE}" 0
     ${LogUninstall} "File: $DESKTOP\${BrandFullName}.lnk"
+    ${LogMsg} "Added Shortcut: $DESKTOP\${BrandFullName}.lnk"
   ${EndIf}
 
   !insertmacro MUI_STARTMENU_WRITE_END
-
-  ; Refresh desktop icons
-  System::Call "shell32::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)"
-SectionEnd
-
-Section /o "IRC Client" Section2
-  Call installChatZilla
-SectionEnd
-
-Section /o "Developer Tools" Section3
-  Call installInspector
-SectionEnd
-
-Section /o "Debug and QA Tools" Section4
-  Call installDebugQA
 SectionEnd
 
-Section /o "Palm Address Book Synchronization Tool" Section5
-  Call installPalmSync
-SectionEnd
-
-Section /o "JavaScript Debugger" Section6
-  Call installVenkman
-SectionEnd
-
-################################################################################
-# Helper Functions
-
-Function installChatZilla
+Section /o "IRC Client" CZ_IDX 
   ${If} ${FileExists} "$EXEDIR\optional\extensions\{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}"
-    SetDetailsPrint textonly
+    SetDetailsPrint both 
     DetailPrint $(STATUS_INSTALL_OPTIONAL)
     SetDetailsPrint none
+
     ${RemoveDir} "$INSTDIR\extensions\{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}"
     ${RemoveDir} "$INSTDIR\extensions\langpack-${AB_CD}@chatzilla.mozilla.org"
     ClearErrors
     ${LogHeader} "Installing IRC Client"
-    StrCpy $R0 "$EXEDIR\optional\extensions\{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}"
-    StrCpy $R1 "$INSTDIR\extensions\{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}"
-    Call DoCopyFiles
+    ${CopyFilesFromDir} "$EXEDIR\optional\extensions\{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}" \
+                        "$INSTDIR\extensions\{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}" \
+                        "$(ERROR_CREATE_DIRECTORY_PREFIX)" \
+                        "$(ERROR_CREATE_DIRECTORY_SUFFIX)"
     ${If} ${FileExists} "$EXEDIR\optional\extensions\langpack-${AB_CD}@chatzilla.mozilla.org"
-      StrCpy $R0 "$EXEDIR\optional\extensions\langpack-${AB_CD}@chatzilla.mozilla.org"
-      StrCpy $R1 "$INSTDIR\extensions\langpack-${AB_CD}@chatzilla.mozilla.org"
-      Call DoCopyFiles
+      ${CopyFilesFromDir} "$EXEDIR\optional\extensions\langpack-${AB_CD}@chatzilla.mozilla.org" \
+                          "$INSTDIR\extensions\langpack-${AB_CD}@chatzilla.mozilla.org" \
+                          "$(ERROR_CREATE_DIRECTORY_PREFIX)" \
+                          "$(ERROR_CREATE_DIRECTORY_SUFFIX)"
     ${EndIf}
   ${EndIf}
-FunctionEnd
+SectionEnd
 
-Function installInspector
+Section /o "Developer Tools" DOMI_IDX 
   ${If} ${FileExists} "$EXEDIR\optional\extensions\inspector@mozilla.org"
-    SetDetailsPrint textonly
+    SetDetailsPrint both 
     DetailPrint $(STATUS_INSTALL_OPTIONAL)
     SetDetailsPrint none
+
     ${RemoveDir} "$INSTDIR\extensions\inspector@mozilla.org"
     ClearErrors
     ${LogHeader} "Installing Developer Tools"
-    StrCpy $R0 "$EXEDIR\optional\extensions\inspector@mozilla.org"
-    StrCpy $R1 "$INSTDIR\extensions\inspector@mozilla.org"
-    Call DoCopyFiles
-  ${EndIf}
-FunctionEnd
+    ${CopyFilesFromDir} "$EXEDIR\optional\extensions\inspector@mozilla.org" \
+                        "$INSTDIR\extensions\inspector@mozilla.org" \
+                        "$(ERROR_CREATE_DIRECTORY_PREFIX)" \
+                        "$(ERROR_CREATE_DIRECTORY_SUFFIX)"
+  ${EndIf} 
+SectionEnd
 
-Function installDebugQA
+Section /o "Debug and QA Tools" DEBUG_IDX 
   ${If} ${FileExists} "$EXEDIR\optional\extensions\debugQA@mozilla.org"
-    SetDetailsPrint textonly
+    SetDetailsPrint both 
     DetailPrint $(STATUS_INSTALL_OPTIONAL)
     SetDetailsPrint none
+
     ${RemoveDir} "$INSTDIR\extensions\debugQA@mozilla.org"
     ClearErrors
     ${LogHeader} "Installing Debug and QA Tools"
-    StrCpy $R0 "$EXEDIR\optional\extensions\debugQA@mozilla.org"
-    StrCpy $R1 "$INSTDIR\extensions\debugQA@mozilla.org"
-    Call DoCopyFiles
+    ${CopyFilesFromDir} "$EXEDIR\optional\extensions\debugQA@mozilla.org" \
+                        "$INSTDIR\extensions\debugQA@mozilla.org" \
+                        "$(ERROR_CREATE_DIRECTORY_PREFIX)" \
+                        "$(ERROR_CREATE_DIRECTORY_SUFFIX)"
   ${EndIf}
-FunctionEnd
+SectionEnd
 
-Function installPalmSync
+Section /o "Palm Address Book Synchronization Tool" PALM_IDX 
   ${If} ${FileExists} "$EXEDIR\optional\extensions\p@m"
-    SetDetailsPrint textonly
+    SetDetailsPrint both
     DetailPrint $(STATUS_INSTALL_OPTIONAL)
     SetDetailsPrint none
+
     ${RemoveDir} "$INSTDIR\extensions\p@m"
     ClearErrors
     ${LogHeader} "Installing Palm Address Book Synchronization Tool"
-    StrCpy $R0 "$EXEDIR\optional\extensions\p@m"
-    StrCpy $R1 "$INSTDIR\extensions\p@m"
-    Call DoCopyFiles
+    ${CopyFilesFromDir} "$EXEDIR\optional\extensions\p@m" \
+                        "$INSTDIR\extensions\p@m" \
+                        "$(ERROR_CREATE_DIRECTORY_PREFIX)" \
+                        "$(ERROR_CREATE_DIRECTORY_SUFFIX)"
   ${EndIf}
-FunctionEnd
+SectionEnd
 
-Function installVenkman
+Section /o "JavaScript Debugger" VENKMAN_IDX 
   ${If} ${FileExists} "$EXEDIR\optional\extensions\{f13b157f-b174-47e7-a34d-4815ddfdfeb8}"
-    SetDetailsPrint textonly
+    SetDetailsPrint both 
     DetailPrint $(STATUS_INSTALL_OPTIONAL)
     SetDetailsPrint none
+
     ${RemoveDir} "$INSTDIR\extensions\{f13b157f-b174-47e7-a34d-4815ddfdfeb8}"
     ${RemoveDir} "$INSTDIR\extensions\langpack-${AB_CD}@venkman.mozilla.org"
     ClearErrors
     ${LogHeader} "Installing JavaScript Debugger"
-    StrCpy $R0 "$EXEDIR\optional\extensions\{f13b157f-b174-47e7-a34d-4815ddfdfeb8}"
-    StrCpy $R1 "$INSTDIR\extensions\{f13b157f-b174-47e7-a34d-4815ddfdfeb8}"
-    Call DoCopyFiles
+    ${CopyFilesFromDir} "$EXEDIR\optional\extensions\{f13b157f-b174-47e7-a34d-4815ddfdfeb8}" \
+                        "$INSTDIR\extensions\langpack-${AB_CD}@venkman.mozilla.org" \
+                        "$(ERROR_CREATE_DIRECTORY_PREFIX)" \
+                        "$(ERROR_CREATE_DIRECTORY_SUFFIX)"
     ${If} ${FileExists} "$EXEDIR\optional\extensions\langpack-${AB_CD}@venkman.mozilla.org"
-      StrCpy $R0 "$EXEDIR\optional\extensions\langpack-${AB_CD}@venkman.mozilla.org"
-      StrCpy $R1 "$INSTDIR\extensions\langpack-${AB_CD}@venkman.mozilla.org"
-      Call DoCopyFiles
+      ${CopyFilesFromDir} "$EXEDIR\optional\extensions\langpack-${AB_CD}@venkman.mozilla.org" \
+                          "$INSTDIR\extensions\langpack-${AB_CD}@venkman.mozilla.org" \
+                          "$(ERROR_CREATE_DIRECTORY_PREFIX)" \
+                          "$(ERROR_CREATE_DIRECTORY_SUFFIX)"
     ${EndIf}
   ${EndIf}
-FunctionEnd
+SectionEnd
+
+; Cleanup operations to perform at the end of the installation.
+Section "-InstallEndCleanup"
+  SetDetailsPrint both
+  DetailPrint "$(STATUS_CLEANUP)"
+  SetDetailsPrint none
+
+  ${LogHeader} "Updating Uninstall Log With Previous Uninstall Log"
+  ${InstallEndCleanupCommon}
+
+  ; Refresh desktop icons
+  System::Call "shell32::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)"
+
+  ; If we have to reboot give SHChangeNotify time to finish the refreshing
+  ; the icons so the OS doesn't display the icons from helper.exe
+  ${If} ${RebootFlag}
+    Sleep 10000
+    ${LogHeader} "Reboot Required To Finish Installation"
+    ; ${FileMainEXE}.moz-upgrade should never exist but just in case...
+    ${Unless} ${FileExists} "$INSTDIR\${FileMainEXE}.moz-upgrade"
+      Rename "$INSTDIR\${FileMainEXE}" "$INSTDIR\${FileMainEXE}.moz-upgrade"
+    ${EndUnless}
 
-; Copies a file to a temporary backup directory and then checks if it is in use
-; by attempting to delete the file. If the file is in use an error is displayed
-; and the user is given the options to either retry or cancel. If cancel is
-; selected then the files are restored.
-Function CheckInUse
-  ${If} ${FileExists} "$INSTDIR\$R1"
-    retry:
-    ClearErrors
-    CopyFiles /SILENT "$INSTDIR\$R1" "$TmpVal\$R1"
-    ${Unless} ${Errors}
-      Delete "$INSTDIR\$R1"
+    ${If} ${FileExists} "$INSTDIR\${FileMainEXE}"
+      ClearErrors
+      Rename "$INSTDIR\${FileMainEXE}" "$INSTDIR\${FileMainEXE}.moz-delete"
+      ${Unless} ${Errors}
+        Delete /REBOOTOK "$INSTDIR\${FileMainEXE}.moz-delete"
+      ${EndUnless}
+    ${EndUnless}
+    ${Unless} ${FileExists} "$INSTDIR\${FileMainEXE}"
+      CopyFiles /SILENT "$INSTDIR\uninstall\helper.exe" "$INSTDIR"
+      FileOpen $0 "$INSTDIR\${FileMainEXE}" w
+      FileWrite $0 "Will be deleted on restart"
+      Rename /REBOOTOK "$INSTDIR\${FileMainEXE}.moz-upgrade" "$INSTDIR\${FileMainEXE}"
+      FileClose $0
+      Delete "$INSTDIR\${FileMainEXE}"
+      Rename "$INSTDIR\helper.exe" "$INSTDIR\${FileMainEXE}"
     ${EndUnless}
-    ${If} ${Errors}
-      StrCpy $0 "$INSTDIR\$R1"
-      ${WordReplace} "$(^FileError_NoIgnore)" "\r\n" "$\r$\n" "+*" $0
-      MessageBox MB_RETRYCANCEL|MB_ICONQUESTION "$0" IDRETRY retry
-      Delete "$TmpVal\$R1"
-      CopyFiles /SILENT "$TmpVal\*" "$INSTDIR\"
-      SetOutPath $INSTDIR
-      RmDir /r "$TmpVal"
-      Quit
+  ${EndIf}
+SectionEnd    
+    
+Function CheckExistingInstall
+  ; If there is a pending file copy from a previous uninstall don't allow
+  ; installing until after the system has rebooted.
+  IfFileExists "$INSTDIR\${FileMainEXE}.moz-upgrade" +1 +4
+  MessageBox MB_YESNO "$(WARN_RESTART_REQUIRED_UPGRADE)" IDNO +2
+  Reboot
+  Quit
+
+  ; If there is a pending file deletion from a previous uninstall don't allow
+  ; installing until after the system has rebooted.
+  IfFileExists "$INSTDIR\${FileMainEXE}.moz-delete" +1 +4
+  MessageBox MB_YESNO "$(WARN_RESTART_REQUIRED_UNINSTALL)" IDNO +2
+  Reboot
+  Quit
+
+  ${If} ${FileExists} "$INSTDIR\${FileMainEXE}"
+    Banner::show /NOUNLOAD "$(BANNER_CHECK_EXISTING)"
+    ${If} "$TmpVal" == "FoundMessageWindow"
+      Sleep 5000
+    ${EndIf}
+    ${PushFilesToCheck}
+    ; Store the return value in $TmpVal so it is less likely to be accidentally
+    ; overwritten elsewhere.
+    ${CheckForFilesInUse} $TmpVal
+
+    Banner::destroy
+
+    ${If} "$TmpVal" == "true"
+      StrCpy $TmpVal "FoundMessageWindow"
+      ${ManualCloseAppPrompt} "${WindowClass}" "$(WARN_MANUALLY_CLOSE_APP_INSTALL)"
+      StrCpy $TmpVal "true"
     ${EndIf}
   ${EndIf}
 FunctionEnd
 
-; Adds a section divider to the human readable log.
-Function WriteLogSeparator
-  FileWrite $fhInstallLog "$\r$\n-------------------------------------------------------------------------------$\r$\n"
-FunctionEnd
-
-; Check whether to display the current page (e.g. if we aren't performing a
-; custom install don't display the custom pages).
-Function CheckCustom
-  ${If} $InstallType != 4
-    Abort
-  ${EndIf}
-FunctionEnd
-
-Function onInstallDeleteFile
-  ${TrimNewLines} "$R9" "$R9"
-  StrCpy $R1 "$R9" 5
-  ${If} $R1 == "File:"
-    StrCpy $R9 "$R9" "" 6
-    ${If} ${FileExists} "$INSTDIR$R9"
-      ClearErrors
-      Delete "$INSTDIR$R9"
-      ${If} ${Errors}
-        ${LogMsg} "** ERROR Deleting File: $INSTDIR$R9 **"
-      ${Else}
-        ${LogMsg} "Deleted File: $INSTDIR$R9"
-      ${EndIf}
-    ${EndIf}
-  ${EndIf}
-  ClearErrors
-  Push 0
-FunctionEnd
-
-; The previous installer removed directories even when they aren't empty so this
-; function does as well.
-Function onInstallRemoveDir
-  ${TrimNewLines} "$R9" "$R9"
-  StrCpy $R1 "$R9" 4
-  ${If} $R1 == "Dir:"
-    StrCpy $R9 "$R9" "" 5
-    StrCpy $R1 "$R9" "" -1
-    ${If} $R1 == "\"
-      StrCpy $R9 "$R9" -1
-    ${EndIf}
-    ${If} ${FileExists} "$INSTDIR$R9"
-      ClearErrors
-      RmDir /r "$INSTDIR$R9"
-      ${If} ${Errors}
-        ${LogMsg} "** ERROR Removing Directory: $INSTDIR$R9 **"
-      ${Else}
-        ${LogMsg} "Removed Directory: $INSTDIR$R9"
-      ${EndIf}
-    ${EndIf}
-  ${EndIf}
-  ClearErrors
-  Push 0
-FunctionEnd
-
-Function GetDiff
-  ${TrimNewLines} "$9" "$9"
-  ${If} $9 != ""
-    FileWrite $R3 "$9$\r$\n"
-    ${LogMsg} "Added To Uninstall Log: $9"
-  ${EndIf}
-  Push 0
-FunctionEnd
-
-Function DoCopyFiles
-  StrLen $R2 $R0
-  ${LocateNoDetails} "$R0" "/L=FD" "CopyFile"
+Function LaunchApp
+  GetFunctionAddress $0 LaunchAppFromElevatedProcess
+  UAC::ExecCodeSegment $0
 FunctionEnd
 
-Function CopyFile
-  StrCpy $R3 $R8 "" $R2
-  retry:
-  ClearErrors
-  ${If} $R6 ==  ""
-    ${Unless} ${FileExists} "$R1$R3\$R7"
-      ClearErrors
-      CreateDirectory "$R1$R3\$R7"
-      ${If} ${Errors}
-        ${LogMsg}  "** ERROR Creating Directory: $R1$R3\$R7 **"
-        StrCpy $0 "$R1$R3\$R7"
-        ${WordReplace} "$(^FileError_NoIgnore)" "\r\n" "$\r$\n" "+*" $0
-        MessageBox MB_RETRYCANCEL|MB_ICONQUESTION "$0" IDRETRY retry
-        Quit
-      ${Else}
-        ${LogMsg}  "Created Directory: $R1$R3\$R7"
-      ${EndIf}
-    ${EndUnless}
-  ${Else}
-    ${Unless} ${FileExists} "$R1$R3"
-      ClearErrors
-      CreateDirectory "$R1$R3"
-      ${If} ${Errors}
-        ${LogMsg}  "** ERROR Creating Directory: $R1$R3 **"
-        StrCpy $0 "$R1$R3"
-        ${WordReplace} "$(^FileError_NoIgnore)" "\r\n" "$\r$\n" "+*" $0
-        MessageBox MB_RETRYCANCEL|MB_ICONQUESTION "$0" IDRETRY retry
-        Quit
-      ${Else}
-        ${LogMsg}  "Created Directory: $R1$R3"
-      ${EndIf}
-    ${EndUnless}
-    ${If} ${FileExists} "$R1$R3\$R7"
-      ClearErrors
-      Delete "$R1$R3\$R7"
-      ${If} ${Errors}
-        ${LogMsg} "** ERROR Deleting File: $R1$R3\$R7 **"
-        StrCpy $0 "$R1$R3\$R7"
-        ${WordReplace} "$(^FileError_NoIgnore)" "\r\n" "$\r$\n" "+*" $0
-        MessageBox MB_RETRYCANCEL|MB_ICONQUESTION "$0" IDRETRY retry
-        Quit
-      ${EndIf}
-    ${EndIf}
-    ClearErrors
-    CopyFiles /SILENT $R9 "$R1$R3"
-    ${If} ${Errors}
-      ${LogMsg} "** ERROR Installing File: $R1$R3\$R7 **"
-      StrCpy $0 "$R1$R3\$R7"
-      ${WordReplace} "$(^FileError_NoIgnore)" "\r\n" "$\r$\n" "+*" $0
-      MessageBox MB_RETRYCANCEL|MB_ICONQUESTION "$0" IDRETRY retry
-      Quit
-    ${Else}
-      ${LogMsg} "Installed File: $R1$R3\$R7"
-    ${EndIf}
-    ; If the file is installed into the installation directory remove the
-    ; installation directory's path from the file path when writing to the
-    ; uninstall.log so it will be a relative path. This allows the same
-    ; helper.exe to be used with zip builds if we supply an uninstall.log.
-    ${WordReplace} "$R1$R3\$R7" "$INSTDIR" "" "+" $R3
-    ${LogUninstall} "File: $R3"
-  ${EndIf}
-  Push 0
-FunctionEnd
-
-; Clean up the old log files. We only diff the first two found since it is
-; possible for there to be several MB and comparing that many would take a very
-; long time to diff.
-Function CleanupOldLogs
-  FindFirst $0 $TmpVal "$INSTDIR\uninstall\*wizard*"
-  StrCmp $TmpVal "" done
-  StrCpy $TmpVal "$INSTDIR\uninstall\$TmpVal"
-
-  FindNext $0 $1
-  StrCmp $1 "" cleanup
-  StrCpy $1 "$INSTDIR\uninstall\$1"
-  Push $1
-  Call DiffOldLogFiles
-  FindClose $0
-  ${DeleteFile} "$1"
-
-  cleanup:
-    StrCpy $2 "$INSTDIR\uninstall\cleanup.log"
-    ${DeleteFile} "$2"
-    FileOpen $R2 $2 w
-    Push $TmpVal
-    ${LineFind} "$INSTDIR\uninstall\$TmpVal" "/NUL" "1:-1" "CleanOldLogFilesCallback"
-    ${DeleteFile} "$INSTDIR\uninstall\$TmpVal"
-  done:
-    FindClose $0
-    FileClose $R2
-    FileClose $R3
-FunctionEnd
-
-Function DiffOldLogFiles
-  StrCpy $R1 "$1"
-  GetTempFileName $R2
-  FileOpen $R3 $R2 w
-  ${TextCompareNoDetails} "$R1" "$TmpVal" "SlowDiff" "GetDiff"
-  FileClose $R3
-  ${FileJoin} "$TmpVal" "$R2" "$TmpVal"
-  ${DeleteFile} "$R2"
-FunctionEnd
-
-Function CleanOldLogFilesCallback
-  ${TrimNewLines} "$R9" $R9
-  ${WordReplace} "$R9" "$INSTDIR" "" "+" $R3
-  ${WordFind} "$R9" "	" "E+1}" $R0
-  IfErrors updater 0
-
-  ${WordFind} "$R0" "Installing: " "E+1}" $R1
-  ${Unless} ${Errors}
-    FileWrite $R2 "File: $R1$\r$\n"
-    GoTo done
-  ${EndUnless}
-
-  ${WordFind} "$R0" "Replacing: " "E+1}" $R1
-  ${Unless} ${Errors}
-    FileWrite $R2 "File: $R1$\r$\n"
-    GoTo done
-  ${EndUnless}
-
-  ${WordFind} "$R0" "Windows Shortcut: " "E+1}" $R1
-  ${Unless} ${Errors}
-    FileWrite $R2 "File: $R1.lnk$\r$\n"
-    GoTo done
-  ${EndUnless}
-
-  ${WordFind} "$R0" "Create Folder: " "E+1}" $R1
-  ${Unless} ${Errors}
-    FileWrite $R2 "Dir: $R1$\r$\n"
-    GoTo done
-  ${EndUnless}
-
-  updater:
-    ${WordFind} "$R9" "installing: " "E+1}" $R0
-    ${Unless} ${Errors}
-      FileWrite $R2 "File: $R0$\r$\n"
-    ${EndUnless}
-
-  done:
-    Push 0
-FunctionEnd
-
-Function LaunchApp
-  ${CloseApp} "true" $(WARN_APP_RUNNING_INSTALL)
-  Exec "$INSTDIR\${FileMainEXE}"
+Function LaunchAppFromElevatedProcess
+  ${ManualCloseAppPrompt} "${WindowClass}" "$(WARN_MANUALLY_CLOSE_APP_LAUNCH)"
+  ; Find the installation directory when launching using GetFunctionAddress
+  ; from an elevated installer since $INSTDIR will not be set in this installer
+  ${StrFilter} "${FileMainEXE}" "+" "" "" $R9
+  ReadRegStr $0 HKLM "Software\Clients\StartMenuInternet\$R9\DefaultIcon" ""
+  ${GetPathFromString} "$0" $0
+  ${GetParent} "$0" $1
+  ; Set our current working directory to the application's install directory
+  ; otherwise the 7-Zip temp directory will be in use and won't be deleted.
+  SetOutPath "$1"
+  Exec "$0"
 FunctionEnd
 
 ################################################################################
 # Language
 
 !insertmacro MOZ_MUI_LANGUAGE 'baseLocale'
 !verbose push
 !verbose 3
@@ -925,147 +712,167 @@ FunctionEnd
 
 ; Set this after the locale files to override it if it is in the locale
 ; using " " for BrandingText will hide the "Nullsoft Install System..." branding
 BrandingText " "
 
 ################################################################################
 # Page pre and leave functions
 
+Function preWelcome
+  ${If} ${FileExists} "$EXEDIR\localized\distribution\modern-wizard.bmp"
+    Delete "$PLUGINSDIR\modern-wizard.bmp"
+    CopyFiles /SILENT "$EXEDIR\localized\distribution\modern-wizard.bmp" "$PLUGINSDIR\modern-wizard.bmp"
+  ${EndIf}
+FunctionEnd
+
+Function showLicense
+  ${If} ${FileExists} "$EXEDIR\localized\distribution\modern-header.bmp"
+  ${AndIf} $hHeaderBitmap == ""
+    Delete "$PLUGINSDIR\modern-header.bmp"
+    CopyFiles /SILENT "$EXEDIR\localized\distribution\modern-header.bmp" "$PLUGINSDIR\modern-header.bmp"
+    ${ChangeMUIHeaderImage} "$PLUGINSDIR\modern-header.bmp"
+  ${EndIf}
+FunctionEnd
+
 Function preOptions
   !insertmacro MUI_HEADER_TEXT "$(OPTIONS_PAGE_TITLE)" "$(OPTIONS_PAGE_SUBTITLE)"
   !insertmacro MUI_INSTALLOPTIONS_DISPLAY "options.ini"
 FunctionEnd
 
 Function leaveOptions
   ${MUI_INSTALLOPTIONS_READ} $0 "options.ini" "Settings" "State"
   ${If} $0 != 0
     Abort
   ${EndIf}
   ${MUI_INSTALLOPTIONS_READ} $R0 "options.ini" "Field 2" "State"
   StrCmp $R0 "1" +1 +2
-  StrCpy $InstallType "1"
+  StrCpy $InstallType ${INSTALLTYPE_BASIC} 
   ${MUI_INSTALLOPTIONS_READ} $R0 "options.ini" "Field 3" "State"
   StrCmp $R0 "1" +1 +2
-  StrCpy $InstallType "4"
+  StrCpy $InstallType ${INSTALLTYPE_CUSTOM}
+
+  ${If} $InstallType != ${INSTALLTYPE_CUSTOM}
+!ifndef NO_INSTDIR_FROM_REG
+    SetShellVarContext all      ; Set SHCTX to HKLM
+    ${GetSingleInstallPath} "Software\Mozilla\${BrandFullNameInternal}" $R9
+    StrCmp "$R9" "false" +1 fix_install_dir
+    SetShellVarContext current  ; Set SHCTX to HKCU
+    ${GetSingleInstallPath} "Software\Mozilla\${BrandFullNameInternal}" $R9
+
+    fix_install_dir:
+    StrCmp "$R9" "false" +2 +1
+    StrCpy $INSTDIR "$R9"
+!endif
+
+    Call CheckExistingInstall
+  ${EndIf}
 FunctionEnd
 
 Function preComponents
-  Call CheckCustom
+  ${CheckCustomCommon}
   !insertmacro checkSuiteComponents
   !insertmacro MUI_HEADER_TEXT "$(OPTIONAL_COMPONENTS_TITLE)" "$(OPTIONAL_COMPONENTS_SUBTITLE)"
   !insertmacro MUI_INSTALLOPTIONS_DISPLAY "components.ini"
 FunctionEnd
 
 Function leaveComponents
   ; If ChatZilla exists then it will be Field 2.
   ; If ChatZilla doesn't exist then DOMi will be Field 2 (when ChatZilla and DOMi
   ; don't exist, debugQA will be Field 2).
   StrCpy $R1 2
   
  ${If} ${FileExists} "$EXEDIR\optional\extensions\{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}"
     ${MUI_INSTALLOPTIONS_READ} $R0 "components.ini" "Field $R1" "State"
     ; State will be 1 for checked and 0 for unchecked so we can use that to set
     ; the section flags for installation.
-    SectionSetFlags 1 $R0
+    SectionSetFlags ${CZ_IDX} $R0
     IntOp $R1 $R1 + 1
   ${Else}
-    SectionSetFlags 1 0 ; Disable install for chatzilla
+    SectionSetFlags ${CZ_IDX} 0 ; Disable install for chatzilla
   ${EndIf}
 
   ${If} ${FileExists} "$EXEDIR\optional\extensions\inspector@mozilla.org"
     ${MUI_INSTALLOPTIONS_READ} $R0 "components.ini" "Field $R1" "State"
     ; State will be 1 for checked and 0 for unchecked so we can use that to set
     ; the section flags for installation.
-    SectionSetFlags 2 $R0
+    SectionSetFlags ${DOMI_IDX} $R0
     IntOp $R1 $R1 + 1
   ${Else}
-    SectionSetFlags 2 0 ; Disable install for DOMi
+    SectionSetFlags ${DOMI_IDX} 0 ; Disable install for DOMi
   ${EndIf}
 
   ${If} ${FileExists} "$EXEDIR\optional\extensions\debugQA@mozilla.org"
     ${MUI_INSTALLOPTIONS_READ} $R0 "components.ini" "Field $R1" "State"
     ; State will be 1 for checked and 0 for unchecked so we can use that to set
     ; the section flags for installation.
-    SectionSetFlags 3 $R0
+    SectionSetFlags ${DEBUG_IDX} $R0
     IntOp $R1 $R1 + 1
   ${Else}
-    SectionSetFlags 3 0 ; Disable install for debugQA
+    SectionSetFlags ${DEBUG_IDX} 0 ; Disable install for debugQA
   ${EndIf}
 
   ${If} ${FileExists} "$EXEDIR\optional\extensions\p@m"
     ${MUI_INSTALLOPTIONS_READ} $R0 "components.ini" "Field $R1" "State"
     ; State will be 1 for checked and 0 for unchecked so we can use that to set
     ; the section flags for installation.
-    SectionSetFlags 4 $R0
+    SectionSetFlags ${PALM_IDX} $R0
     IntOp $R1 $R1 + 1
   ${Else}
-    SectionSetFlags 4 0 ; Disable install for palmsync
+    SectionSetFlags ${PALM_IDX} 0 ; Disable install for palmsync
   ${EndIf}
 
   ${If} ${FileExists} "$EXEDIR\optional\extensions\{f13b157f-b174-47e7-a34d-4815ddfdfeb8}"
     ${MUI_INSTALLOPTIONS_READ} $R0 "components.ini" "Field $R1" "State"
     ; State will be 1 for checked and 0 for unchecked so we can use that to set
     ; the section flags for installation.
-    SectionSetFlags 5 $R0
+    SectionSetFlags ${VENKMAN_IDX} $R0
     IntOp $R1 $R1 + 1
   ${Else}
-    SectionSetFlags 5 0 ; Disable install for venkman
+    SectionSetFlags ${VENKMAN_IDX} 0 ; Disable install for venkman
   ${EndIf}
 FunctionEnd
 
 Function preDirectory
-  ${If} $InstallType != 4
-    ${CheckDiskSpace} $R9
-    ${If} $R9 != "false"
-      ${CanWriteToInstallDir} $R9
-      ${If} $R9 != "false"
-        Abort
-      ${EndIf}
-    ${EndIf}
-  ${EndIf}
+  ${PreDirectoryCommon}
 FunctionEnd
 
 Function leaveDirectory
-  ${CheckDiskSpace} $R9
-  ${If} $R9 == "false"
-    MessageBox MB_OK "$(WARN_DISK_SPACE)"
-    Abort
-  ${EndIf}
-
-  ${CanWriteToInstallDir} $R9
-  ${If} $R9 == "false"
-    MessageBox MB_OK "$(WARN_WRITE_ACCESS)"
-    Abort
-  ${EndIf}
+  ${LeaveDirectoryCommon} "$(WARN_DISK_SPACE)" "$(WARN_WRITE_ACCESS)"
 FunctionEnd
 
 Function preShortcuts
-  Call CheckCustom
+  ${CheckCustomCommon}
   !insertmacro MUI_HEADER_TEXT "$(SHORTCUTS_PAGE_TITLE)" "$(SHORTCUTS_PAGE_SUBTITLE)"
   !insertmacro MUI_INSTALLOPTIONS_DISPLAY "shortcuts.ini"
 FunctionEnd
 
 Function leaveShortcuts
   ${MUI_INSTALLOPTIONS_READ} $0 "shortcuts.ini" "Settings" "State"
   ${If} $0 != 0
     Abort
   ${EndIf}
   ${MUI_INSTALLOPTIONS_READ} $AddDesktopSC "shortcuts.ini" "Field 2" "State"
   ${MUI_INSTALLOPTIONS_READ} $AddStartMenuSC "shortcuts.ini" "Field 3" "State"
   ${MUI_INSTALLOPTIONS_READ} $AddQuickLaunchSC "shortcuts.ini" "Field 4" "State"
 FunctionEnd
 
 Function preStartMenu
-  Call CheckCustom
+  ${CheckCustomCommon}
   ${If} $AddStartMenuSC != 1
     Abort
   ${EndIf}
 FunctionEnd
 
+Function leaveStartMenu
+  ${If} $InstallType == ${INSTALLTYPE_CUSTOM}
+    Call CheckExistingInstall
+  ${EndIf}
+FunctionEnd
+
 Function preSummary
   WriteINIStr "$PLUGINSDIR\summary.ini" "Settings" NumFields "3"
 
   WriteINIStr "$PLUGINSDIR\summary.ini" "Field 1" Type   "label"
   WriteINIStr "$PLUGINSDIR\summary.ini" "Field 1" Text   "$(SUMMARY_INSTALLED_TO)"
   WriteINIStr "$PLUGINSDIR\summary.ini" "Field 1" Left   "0"
   WriteINIStr "$PLUGINSDIR\summary.ini" "Field 1" Right  "-1"
   WriteINIStr "$PLUGINSDIR\summary.ini" "Field 1" Top    "5"
@@ -1095,205 +902,60 @@ Function preSummary
     WriteINIStr "$PLUGINSDIR\summary.ini" "Field 4" Left   "0"
     WriteINIStr "$PLUGINSDIR\summary.ini" "Field 4" Right  "-1"
     WriteINIStr "$PLUGINSDIR\summary.ini" "Field 4" Top    "35"
     WriteINIStr "$PLUGINSDIR\summary.ini" "Field 4" Bottom "45"
 
     WriteINIStr "$PLUGINSDIR\summary.ini" "Settings" NumFields "4"
   ${EndIf}
 
-  ReadINIStr $0 "$PLUGINSDIR\options.ini" "Field 6" "State"
-  ${If} "$0" == "1"
-    ${If} "$TmpVal" == "true"
-      ; To insert this control reset Top / Bottom for controls below this one
-      WriteINIStr "$PLUGINSDIR\summary.ini" "Field 4" Top    "50"
-      WriteINIStr "$PLUGINSDIR\summary.ini" "Field 4" Bottom "60"
-      StrCpy $0 "5"
-    ${Else}
-      StrCpy $0 "4"
-    ${EndIf}
-
-    WriteINIStr "$PLUGINSDIR\summary.ini" "Field $0" Type   "label"
-    WriteINIStr "$PLUGINSDIR\summary.ini" "Field $0" Text   "$(SUMMARY_MAKE_DEFAULT)"
-    WriteINIStr "$PLUGINSDIR\summary.ini" "Field $0" Left   "0"
-    WriteINIStr "$PLUGINSDIR\summary.ini" "Field $0" Right  "-1"
-    WriteINIStr "$PLUGINSDIR\summary.ini" "Field $0" Top    "35"
-    WriteINIStr "$PLUGINSDIR\summary.ini" "Field $0" Bottom "45"
-
-    WriteINIStr "$PLUGINSDIR\summary.ini" "Settings" NumFields "$0"
-  ${EndIf}
-
   !insertmacro MUI_HEADER_TEXT "$(SUMMARY_PAGE_TITLE)" "$(SUMMARY_PAGE_SUBTITLE)"
 
   ; The Summary custom page has a textbox that will automatically receive
   ; focus. This sets the focus to the Install button instead.
   !insertmacro MUI_INSTALLOPTIONS_INITDIALOG "summary.ini"
   GetDlgItem $0 $HWNDPARENT 1
   System::Call "user32::SetFocus(i r0, i 0x0007, i,i)i"
-
   ${MUI_INSTALLOPTIONS_READ} $1 "summary.ini" "Field 2" "HWND"                  
   SendMessage $1 ${WM_SETTEXT} 0 "STR:$INSTDIR"      
   !insertmacro MUI_INSTALLOPTIONS_SHOW
 FunctionEnd
 
-Function leaveInstFiles
-  FileClose $fhUninstallLog
-  ; Diff and add missing entries from the previous file log if it exists
-  ${If} ${FileExists} "$INSTDIR\uninstall\uninstall.bak"
-    SetDetailsPrint textonly
-    DetailPrint $(STATUS_CLEANUP)
-    SetDetailsPrint none
-    ${LogHeader} "Updating Uninstall Log With Previous Uninstall Log"
-    StrCpy $R0 "$INSTDIR\uninstall\uninstall.log"
-    StrCpy $R1 "$INSTDIR\uninstall\uninstall.bak"
-    GetTempFileName $R2
-    FileOpen $R3 $R2 w
-    ${TextCompareNoDetails} "$R1" "$R0" "SlowDiff" "GetDiff"
-    FileClose $R3
-    ${Unless} ${Errors}
-      ${FileJoin} "$INSTDIR\uninstall\uninstall.log" "$R2" "$INSTDIR\uninstall\uninstall.log"
-    ${EndUnless}
-    ${DeleteFile} "$INSTDIR\uninstall\uninstall.bak"
-    ${DeleteFile} "$R2"
+Function leaveSummary
+  ${If} $InstallType != ${INSTALLTYPE_CUSTOM}
+    ; Set DOM Inspector, Venkman, ChatZilla to be installed
+    SectionSetFlags ${DOMI_IDX} 1
+    SectionSetFlags ${VENKMAN_IDX} 1
+    SectionSetFlags ${CZ_IDX} 1
   ${EndIf}
-
-  Call WriteLogSeparator
-  ${GetTime} "" "L" $0 $1 $2 $3 $4 $5 $6
-  FileWrite $fhInstallLog "${BrandFullName} Installation Finished: $2-$1-$0 $4:$5:$6$\r$\n"
-  FileClose $fhInstallLog
+  ; Try to delete the app executable and if we can't delete it try to find the
+  ; app's message window and prompt the user to close the app. This allows
+  ; running an instance that is located in another directory. If for whatever
+  ; reason there is no message window we will just rename the app's files and
+  ; then remove them on restart.
+  ClearErrors
+  ${DeleteFile} "$INSTDIR\${FileMainEXE}"
+  ${If} ${Errors}
+    ${ManualCloseAppPrompt} "${WindowClass}" "$(WARN_MANUALLY_CLOSE_APP_INSTALL)"
+  ${EndIf}
 FunctionEnd
 
 ; When we add an optional action to the finish page the cancel button is
 ; enabled. This disables it and leaves the finish button as the only choice.
 Function preFinish
+  ${EndInstallLog} "${BrandFullName}"
   !insertmacro MUI_INSTALLOPTIONS_WRITE "ioSpecial.ini" "settings" "cancelenabled" "0"
 FunctionEnd
 
 ################################################################################
 # Initialization Functions
 
 Function .onInit
-  ${GetParameters} $R0
-  ${If} $R0 != ""
-    ClearErrors
-    ${GetOptions} "$R0" "-ms" $R1
-    ${If} ${Errors}
-      ; Default install type
-      StrCpy $InstallType "1"
-      ; Support for specifying an installation configuration file.
-      ClearErrors
-      ${GetOptions} "$R0" "/INI=" $R1
-      ${Unless} ${Errors}
-        ; The configuration file must also exist
-        ${If} ${FileExists} "$R1"
-          SetSilent silent
-          ReadINIStr $0 $R1 "Install" "InstallDirectoryName"
-          ${If} $0 != ""
-            StrCpy $INSTDIR "$PROGRAMFILES\$0"
-          ${Else}
-            ReadINIStr $0 $R1 "Install" "InstallDirectoryPath"
-            ${If} $$0 != ""
-              StrCpy $INSTDIR "$0"
-            ${EndIf}
-          ${EndIf}
-
-          ${If} $INSTDIR == ""
-            ; Check if there is an existing uninstall registry entry for this
-            ; version of the application and if present install into that location
-            ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal} (${AppVersion})" "InstallLocation"
-            ${If} $0 == ""
-              StrCpy $INSTDIR "$PROGRAMFILES\${BrandFullName}"
-            ${Else}
-              GetFullPathName $INSTDIR "$0"
-              ${Unless} ${FileExists} "$INSTDIR"
-                StrCpy $INSTDIR "$PROGRAMFILES\${BrandFullName}"
-              ${EndUnless}
-            ${EndIf}
-          ${EndIf}
-
-          ; Quit if we are unable to create the installation directory or we are
-          ; unable to write to a file in the installation directory.
-          ClearErrors
-          ${If} ${FileExists} "$INSTDIR"
-            GetTempFileName $R2 "$INSTDIR"
-            FileOpen $R3 $R2 w
-            FileWrite $R3 "Write Access Test"
-            FileClose $R3
-            Delete $R2
-            ${If} ${Errors}
-              Quit
-            ${EndIf}
-          ${Else}
-            CreateDirectory "$INSTDIR"
-            ${If} ${Errors}
-              Quit
-            ${EndIf}
-          ${EndIf}
+  ${InstallOnInitCommon} "$(WARN_UNSUPPORTED_MSG)"
 
-          ReadINIStr $0 $R1 "Install" "CloseAppNoPrompt"
-          ${If} $0 == "true"
-            ; Try to close the app if the exe is in use.
-            ClearErrors
-            ${If} ${FileExists} "$INSTDIR\${FileMainEXE}"
-              ${DeleteFile} "$INSTDIR\${FileMainEXE}"
-            ${EndIf}
-            ${If} ${Errors}
-              ClearErrors
-              ${CloseApp} "false" ""
-              ClearErrors
-              ${DeleteFile} "$INSTDIR\${FileMainEXE}"
-              ; If unsuccessful try one more time and if it still fails Quit
-              ${If} ${Errors}
-                ClearErrors
-                ${CloseApp} "false" ""
-                ClearErrors
-                ${DeleteFile} "$INSTDIR\${FileMainEXE}"
-                ${If} ${Errors}
-                  Quit
-                ${EndIf}
-              ${EndIf}
-            ${EndIf}
-          ${EndIf}
-
-          ReadINIStr $0 $R1 "Install" "QuickLaunchShortcut"
-          ${If} $0 == "false"
-            StrCpy $AddQuickLaunchSC "0"
-          ${Else}
-            StrCpy $AddQuickLaunchSC "1"
-          ${EndIf}
-
-          ReadINIStr $0 $R1 "Install" "DesktopShortcut"
-          ${If} $0 == "false"
-            StrCpy $AddDesktopSC "0"
-          ${Else}
-            StrCpy $AddDesktopSC "1"
-          ${EndIf}
-
-          ReadINIStr $0 $R1 "Install" "StartMenuShortcuts"
-          ${If} $0 == "false"
-            StrCpy $AddStartMenuSC "0"
-          ${Else}
-            StrCpy $AddStartMenuSC "1"
-          ${EndIf}
-
-          ReadINIStr $0 $R1 "Install" "StartMenuDirectoryName"
-          ${If} $0 != ""
-            StrCpy $StartMenuDir "$0"
-          ${EndIf}
-        ${EndIf}
-      ${EndUnless}
-    ${Else}
-      ; Support for the deprecated -ms command line argument. The new command
-      ; line arguments are not supported when -ms is used.
-      SetSilent silent
-    ${EndIf}
-  ${EndIf}
-  ClearErrors
-
-  StrCpy $LANGUAGE 0
   !insertmacro MUI_INSTALLOPTIONS_EXTRACT "options.ini"
   !insertmacro MUI_INSTALLOPTIONS_EXTRACT "components.ini"
   !insertmacro MUI_INSTALLOPTIONS_EXTRACT "shortcuts.ini"
   !insertmacro MUI_INSTALLOPTIONS_EXTRACT "summary.ini"
 
   ; Setup the options.ini file for the Custom Options Page
   WriteINIStr "$PLUGINSDIR\options.ini" "Settings" NumFields "5"
 
@@ -1368,15 +1030,25 @@ Function .onInit
   WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Type   "checkbox"
   WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Text   "$(ICONS_QUICKLAUNCH)"
   WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Left   "15"
   WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Right  "-1"
   WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Top    "60"
   WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Bottom "70"
   WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" State  "1"
 
+  StrCpy $LANGUAGE 0
+
   ; There must always be nonlocalized and localized directories.
-  ${GetSize} "$EXEDIR\nonlocalized\" "/S=0K" $1 $8 $9
-  ${GetSize} "$EXEDIR\localized\" "/S=0K" $2 $8 $9
-  IntOp $0 $1 + $2
-  SectionSetSize 0 $0
+  ${GetSize} "$EXEDIR\nonlocalized\" "/S=0K" $R5 $R7 $R8
+  ${GetSize} "$EXEDIR\localized\" "/S=0K" $R6 $R7 $R8
+  IntOp $R8 $R5 + $R6
+  SectionSetSize ${APP_IDX} $R8
 
+  ; Initialize $hHeaderBitmap to prevent redundant changing of the bitmap if
+  ; the user clicks the back button
+  StrCpy $hHeaderBitmap ""
 FunctionEnd
+
+Function .onGUIEnd
+  ${OnEndCommon}
+FunctionEnd
+
--- a/suite/installer/windows/nsis/shared.nsh
+++ b/suite/installer/windows/nsis/shared.nsh
@@ -31,86 +31,241 @@
 # decision by deleting the provisions above and replace them with the notice
 # and other provisions required by the GPL or the LGPL. If you do not delete
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK *****
 
 !macro PostUpdate
-  SetShellVarContext all
-  ${SetStartMenuInternet}
-  ${SetClientsMail}
-
   ; Remove registry entries for non-existent apps and for apps that point to our
   ; install location in the Software\Mozilla key and uninstall registry entries
   ; that point to our install location for both HKCU and HKLM.
-  SetShellVarContext current  ; Set SHCTX to HKCU
+  SetShellVarContext current  ; Set SHCTX to the current user (e.g. HKCU) 
   ${RegCleanMain} "Software\Mozilla"
   ${RegCleanUninstall}
+  ${UpdateProtocolHandlers}
 
-  SetShellVarContext all  ; Set SHCTX to HKLM
-  ${RegCleanMain} "Software\Mozilla"
-  ${RegCleanUninstall}
+  ClearErrors
+  WriteRegStr HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" "Write Test"
+  ${If} ${Errors}
+    StrCpy $TmpVal "HKCU" ; used primarily for logging
+  ${Else}
+    DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest"
+    SetShellVarContext all ; Set SHCTX to all users (e.g. HKLM)
+    StrCpy $TmpVal "HKLM" ; used primarily for logging
+    ${RegCleanMain} "Software\Mozilla"
+    ${RegCleanUninstall}
+    ${SetStartMenuInternet}
+    ${FixShellIconHandler}
+    ${SetUninstallKeys}
+    ${UpdateProtocolHandlers}
+
+    ReadRegStr $0 HKLM "Software\mozilla.org\Mozilla" "CurrentVersion"
+    ${If} "$0" != "${GREVersion}"
+      WriteRegStr HKLM "Software\mozilla.org\Mozilla" "CurrentVersion" "${GREVersion}"
+    ${EndIf}
+
+    ; Only update the Clients\Mail registry key values if they don't exist or
+    ; this installation is the same as the one set in those keys.
+    ReadRegStr $0 HKLM "Software\Clients\Mail\${BrandFullNameInternal}\DefaultIcon" ""
+    ${GetPathFromString} "$0" $0
+    ${GetParent} "$0" $0
+    ${If} ${FileExists} "$0"
+      ${GetLongPath} "$0" $0
+    ${EndIf}
+    ${If} "$0" == "$INSTDIR"
+      ${SetClientsMail}
+    ${EndIf}
+
+    ; Only update the Clients\News registry key values if they don't exist or
+    ; this installation is the same as the one set in those keys.
+    ReadRegStr $0 HKLM "Software\Clients\News\${BrandFullNameInternal}\DefaultIcon" ""
+    ${GetPathFromString} "$0" $0
+    ${GetParent} "$0" $0
+    ${If} ${FileExists} "$0"
+      ${GetLongPath} "$0" $0
+    ${EndIf}
+    ${If} "$0" == "$INSTDIR"
+      ${SetClientsNews}
+    ${EndIf}
+  ${EndIf}
 
   ; Add Software\Mozilla\ registry entries
   ${SetAppKeys}
 
-  ${SetUninstallKeys}
+  ${FixClassKeys}
 
-  ${FixClassKeys}
+  ; Remove files that may be left behind by the application in the
+  ; VirtualStore directory.
+  ${CleanVirtualStore}
 !macroend
 !define PostUpdate "!insertmacro PostUpdate"
 
 !macro SetAsDefaultAppUser
   SetShellVarContext current
-  ${SetHandlers}
+
+  ; It is only possible to set this installation of the application as the
+  ; handler for the various types if those types were added to the respective
+  ; HKLM\Clients registry keys.
+  ; http://support.microsoft.com/kb/297878
+  ${GetParameters} $R0
+
+  ClearErrors
+  ${GetOptions} "$R0" "Browser" $R1
+  ${Unless} ${Errors}
+    ${StrFilter} "${FileMainEXE}" "+" "" "" $R9
+    ClearErrors
+    ReadRegStr $0 HKLM "Software\Clients\StartMenuInternet\$R9\DefaultIcon" ""
+    ${GetPathFromString} "$0" $0
+    ${GetParent} "$0" $0
+    ${If} ${FileExists} "$0"
+      ${GetLongPath} "$0" $0
+    ${EndIf}
+    ${If} "$0" != "$INSTDIR"
+      DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest"
+      ClearErrors
+      WriteRegStr HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" "Write Test"
+      ${If} ${Errors}
+        ; Prevent multiple elevation requests
+        ClearErrors
+        ${GetOptions} "$R0" "/UAC:" $R1
+        ${Unless} ${Errors}
+          Quit
+        ${EndUnless}
+        ${ElevateUAC}
+      ${EndIf}
+      DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest"
+      ${SetStartMenuInternet}
+    ${EndIf}
+    SetShellVarContext all  ; Set SHCTX to all users (e.g. HKLM)
+    ${FixShellIconHandler}
+    WriteRegStr HKCU "Software\Clients\StartMenuInternet" "" "$R9"
+
+    ${If} ${AtLeastWinVista}
+      ClearErrors
+      ReadRegStr $0 HKLM "Software\RegisteredApplications" "${AppRegName}"
+      ; Only register as the handler on Vista if the app registry name exists
+      ; under the RegisteredApplications registry key.
+      ${Unless} ${Errors}
+        AppAssocReg::SetAppAsDefaultAll "${AppRegName}"
+      ${EndUnless}
+    ${EndIf}
+
+    SetShellVarContext current  ; Set SHCTX to the current user (e.g. HKCU)
+    ${SetHandlersBrowser}
+  ${EndUnless} 
+
+  ClearErrors
+  ${GetOptions} "$R0" "Mail" $R1
+  ${Unless} ${Errors}
+    ReadRegStr $0 HKLM "Software\Clients\Mail\${BrandFullNameInternal}\DefaultIcon" ""
+    ${GetPathFromString} "$0" $0
+    ${GetParent} "$0" $0
+    ${If} ${FileExists} "$0"
+      ${GetLongPath} "$0" $0
+    ${EndIf}
+    ${If} "$0" != "$INSTDIR"
+      DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest"
+      ClearErrors
+      WriteRegStr HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" "Write Test"
+      ${If} ${Errors}
+        ; Prevent multiple elevation requests
+        ClearErrors
+        ${GetOptions} "$R0" "/UAC:" $R1
+        ${Unless} ${Errors}
+          Quit
+        ${EndUnless}
+        ${ElevateUAC}
+      ${EndIf}
+      DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest"
+      SetShellVarContext all     ; Set SHCTX to all users (e.g. HKLM)
+      ${SetClientsMail}
+    ${EndIf}
+    GetFunctionAddress $0 SetAsDefaultMailAppUser
+    UAC::ExecCodeSegment $0
+  ${EndUnless}
+
+  ClearErrors
+  ${GetOptions} "$R0" "News" $R1
+  ${Unless} ${Errors}
+    ReadRegStr $0 HKLM "Software\Clients\News\${BrandFullNameInternal}\DefaultIcon" ""
+    ${GetPathFromString} "$0" $0
+    ${GetParent} "$0" $0
+    ${If} ${FileExists} "$0"
+      ${GetLongPath} "$0" $0
+    ${EndIf}
+    ${If} "$0" != "$INSTDIR"
+      DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest"
+      ClearErrors
+      WriteRegStr HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" "Write Test"
+      ${If} ${Errors}
+        ; Prevent multiple elevation requests
+        ClearErrors
+        ${GetOptions} "$R0" "/UAC:" $R1
+        ${Unless} ${Errors}
+          Quit
+        ${EndUnless}
+        ${ElevateUAC}
+      ${EndIf}
+      DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest"
+      SetShellVarContext all     ; Set SHCTX to all users (e.g. HKLM)
+      ${SetClientsNews}
+    ${EndIf}
+    GetFunctionAddress $0 SetAsDefaultNewsAppUser
+    UAC::ExecCodeSegment $0
+  ${EndUnless}
 !macroend
 !define SetAsDefaultAppUser "!insertmacro SetAsDefaultAppUser"
 
 !macro SetAsDefaultAppGlobal
-  SetShellVarContext all
-  ${SetHandlers}
+  SetShellVarContext all      ; Set SHCTX to all users (e.g. HKLM)
+  ${SetHandlersBrowser}
+  ${SetHandlersMail}
+  ${SetHandlersNews}
   ${SetStartMenuInternet}
+  ${SetClientsMail}
+  ${SetClientsNews}
+  ${FixShellIconHandler}
+  ${ShowShortcuts}
+  ${StrFilter} "${FileMainEXE}" "+" "" "" $R9
   WriteRegStr HKLM "Software\Clients\StartMenuInternet" "" "$R9"
-  ${SetClientsMail}
   WriteRegStr HKLM "Software\Clients\Mail" "" "${BrandFullNameInternal}"
-  ${ShowShortcuts}
 !macroend
 !define SetAsDefaultAppGlobal "!insertmacro SetAsDefaultAppGlobal"
 
 !macro HideShortcuts
   StrCpy $R1 "Software\Clients\Mail\${BrandFullNameInternal}\InstallInfo"
   WriteRegDWORD HKLM $R1 "IconsVisible" 0
   SetShellVarContext all  ; Set $DESKTOP to All Users
   ${Unless} ${FileExists} "$DESKTOP\${BrandFullName}.lnk"
     SetShellVarContext current  ; Set $DESKTOP to the current user's desktop
   ${EndUnless}
 
   ${If} ${FileExists} "$DESKTOP\${BrandFullName}.lnk"
     ShellLink::GetShortCutArgs "$DESKTOP\${BrandFullName}.lnk"
     Pop $0
-    ${If} $0 == ""
+    ${If} "$0" == ""
       ShellLink::GetShortCutTarget "$DESKTOP\${BrandFullName}.lnk"
       Pop $0
       ; Needs to handle short paths
-      ${If} $0 == "$INSTDIR\${FileMainEXE}"
+      ${If} "$0" == "$INSTDIR\${FileMainEXE}"
         Delete "$DESKTOP\${BrandFullName}.lnk"
       ${EndIf}
     ${EndIf}
   ${EndIf}
 
   ${If} ${FileExists} "$QUICKLAUNCH\${BrandFullName}.lnk"
     ShellLink::GetShortCutArgs "$QUICKLAUNCH\${BrandFullName}.lnk"
     Pop $0
-    ${If} $0 == ""
+    ${If} "$0" == ""
       ShellLink::GetShortCutTarget "$QUICKLAUNCH\${BrandFullName}.lnk"
       Pop $0
       ; Needs to handle short paths
-      ${If} $0 == "$INSTDIR\${FileMainEXE}"
+      ${If} "$0" == "$INSTDIR\${FileMainEXE}"
         Delete "$QUICKLAUNCH\${BrandFullName}.lnk"
       ${EndIf}
     ${EndIf}
   ${EndIf}
 !macroend
 !define HideShortcuts "!insertmacro HideShortcuts"
 
 !macro ShowShortcuts
@@ -130,66 +285,110 @@
   ${EndUnless}
   ${Unless} ${FileExists} "$QUICKLAUNCH\${BrandFullName}.lnk"
     CreateShortCut "$QUICKLAUNCH\${BrandFullName}.lnk" "$INSTDIR\${FileMainEXE}" "" "$INSTDIR\${FileMainEXE}" 0
     ShellLink::SetShortCutWorkingDirectory "$QUICKLAUNCH\${BrandFullName}.lnk" "$INSTDIR"
   ${EndUnless}
 !macroend
 !define ShowShortcuts "!insertmacro ShowShortcuts"
 
-!macro SetHandlers
-  GetFullPathName $8 "$INSTDIR\${FileMainEXE}"
+!macro SetHandlersBrowser
+  ${GetLongPath} "$INSTDIR\${FileMainEXE}" $8
 
   StrCpy $0 "SOFTWARE\Classes"
-  StrCpy $2 "$\"$8$\" -url $\"%1$\" -requestPending"
-  StrCpy $2 "$\"$8$\" -mail $\"%1$\""
-  StrCpy $3 "$\"$8$\" -compose $\"%1$\""
-
-  ; BROWSER part
-  ; Associate the file handlers with SeaMonkeyHTML
-  WriteRegStr SHCTX "$0\.htm"   "" "SeaMonkeyHTML"
-  WriteRegStr SHCTX "$0\.html"  "" "SeaMonkeyHTML"
-  WriteRegStr SHCTX "$0\.shtml" "" "SeaMonkeyHTML"
-  WriteRegStr SHCTX "$0\.xht"   "" "SeaMonkeyHTML"
-  WriteRegStr SHCTX "$0\.xhtml" "" "SeaMonkeyHTML"
+  StrCpy $1 "$\"$8$\" -requestPending -osint -url $\"%1$\""
+  StrCpy $2 "$\"$8$\" -url $\"%1$\""
+  StrCpy $3 "$\"%1$\",,0,0,,,,"
 
   ; An empty string is used for the 5th param because SeaMonkeyHTML is not a
   ; protocol handler
-  ${AddHandlerValues} "$0\SeaMonkeyHTML" "$2" "$INSTDIR\chrome\icons\default\html-file.ico" "${AppRegName} Document" "" "true"
-
-  ${AddHandlerValues} "$0\SeaMonkeyURL" "$2" "$8,0" "${AppRegName} URL" "true" "true"
-  ${AddHandlerValues} "$0\gopher" "$2" "$8,0" "URL:Gopher Protocol" "true" "true"
+  ${AddHandlerValues} "$0\SeaMonkeyHTML" "$2" \
+                      "$INSTDIR\chrome\icons\default\html-file.ico" \
+                      "${AppRegName} Document" "" ""
+  ${AddDDEHandlerValues} "SeaMonkeyURL" "$1" "$8,0" "{AppRegName} URL" "true" \
+                         "${DDEApplication}" "$3" "WWW_OpenURL"
 
   ; An empty string is used for the 4th & 5th params because the following
   ; protocol handlers already have a display name and additional keys required
   ; for a protocol handler.
-  ${AddHandlerValues} "$0\ftp" "$2" "$8,0" "" "" "true"
-  ${AddHandlerValues} "$0\http" "$2" "$8,0" "" "" "true"
-  ${AddHandlerValues} "$0\https" "$2" "$8,0" "" "" "true"
+  ${AddDDEHandlerValues} "ftp" "$1" "$8,0" "" "" "${DDEApplication}" "$3" "WWW_OpenURL"
+  ${AddDDEHandlerValues} "http" "$1" "$8,0" "" "" "${DDEApplication}" "$3" "WWW_OpenURL"
+  ${AddDDEHandlerValues} "https" "$1" "$8,0" "" "" "${DDEApplication}" "$3" "WWW_OpenURL"
+
+  ${AddDDEHandlerValues} "gopher" "$1" "$8,0" "URL:Gopher Protocol" "true" \
+                         "${DDEApplication}" "$3" "WWW_OpenURL"
+
+  ReadRegStr $6 HKCR ".htm" ""
+  ${If} "$6" != "SeaMonkeyHTML"
+    WriteRegStr SHCTX "$0\.htm" "" "SeaMonkeyHTML"
+  ${EndIf}
+
+  ReadRegStr $6 HKCR ".html" ""
+  ${If} "$6" != "SeaMonkeyHTML"
+    WriteRegStr SHCTX "$0\.html" "" "SeaMonkeyHTML"
+  ${EndIf}
 
-  ; MAIL/NEWS part
-  ; Associate the .eml file handler with SeaMonkeyEML
-  WriteRegStr SHCTX "$0\.eml"   "" "SeaMonkeyEML"
+  ReadRegStr $6 HKCR ".shtml" ""
+  ${If} "$6" != "SeaMonkeyHTML"
+    WriteRegStr SHCTX "$0\.shtml" "" "SeaMonkeyHTML"
+  ${EndIf}
+
+  ReadRegStr $6 HKCR ".xht" ""
+  ${If} "$6" != "SeaMonkeyHTML"
+     WriteRegStr SHCTX "$0\.xht" "" "SeaMonkeyHTML"
+  ${EndIf}
+
+  ReadRegStr $6 HKCR ".xhtml" ""
+  ${If} "$6" != "SeaMonkeyHTML"
+    WriteRegStr SHCTX "$0\.xhtml" "" "SeaMonkeyHTML"
+  ${EndIf}
+!macroend
+!define SetHandlersBrowser "!insertmacro SetHandlersBrowser"
+
+!macro SetHandlersMail
+  ${GetLongPath} "$INSTDIR\${FileMainEXE}" $8
+
+  StrCpy $0 "SOFTWARE\Classes"
+  StrCpy $1 "$\"$8$\" $\"%1$\""
+  StrCpy $2 "$\"$8$\" -osint -compose $\"%1$\""
 
   ; An empty string is used for the 5th param because SeaMonkeyEML is not a
   ; protocol handler
-  ${AddHandlerValues} "$0\SeaMonkeyEML"  "$2" "$INSTDIR\chrome\icons\default\misc-file.ico" "${AppRegNameMail} Document" "" ""
+  ${AddHandlerValues} "$0\SeaMonkeyEML"  "$1" "$INSTDIR\chrome\icons\default\misc-file.ico" "${AppRegNameMail} Document" "" ""
+
+  ${AddHandlerValues} "$0\SeaMonkeyCOMPOSE" "$2" "$8,0" "${AppRegNameMail} URL" "true" ""
+
+  ; An empty string is used for the 4th & 5th params because the following
+  ; protocol handler already has a display name and additional keys required
+  ; for a protocol handler.
+  ${AddHandlerValues} "$0\mailto" "$2" "$8,0" "${AppRegNameMail} URL" "true" ""
 
-  ${AddHandlerValues} "$0\SeaMonkeyCOMPOSE"  "$3" "$8,0" "${AppRegNameMail} URL" "true" ""
-  ${AddHandlerValues} "$0\SeaMonkeyNEWS" "$2" "$8,0" "${AppRegNameNews} URL" "true" ""
+  ; Associate the file handlers with SeaMonkeyEML
+  ReadRegStr $6 HKCR ".eml" ""
+  ${If} "$6" != "SeaMonkeyEML"
+    WriteRegStr SHCTX "$0\.eml"   "" "SeaMonkeyEML"
+  ${EndIf}
+!macroend
+!define SetHandlersMail "!insertmacro SetHandlersMail"
 
+!macro SetHandlersNews
+  ${GetLongPath} "$INSTDIR\${FileMainEXE}" $8
+  StrCpy $0 "SOFTWARE\Classes"
+  StrCpy $1 "$\"$8$\" -osint -mail $\"%1$\""
+
+  ${AddHandlerValues} "$0\SeaMonkeyNEWS" "$1" "$8,0" "${AppRegNameNews} URL" "true" ""
   ; An empty string is used for the 4th & 5th params because the following
   ; protocol handlers already have a display name and additional keys required
   ; for a protocol handler.
-  ${AddHandlerValues} "$0\mailto" "$3" "$8,0" "${AppRegNameMail} URL" "true" ""
   ${AddHandlerValues} "$0\news"   "$2" "$8,0" "${AppRegNameNews} URL" "true" ""
   ${AddHandlerValues} "$0\nntp"   "$2" "$8,0" "${AppRegNameNews} URL" "true" ""
   ${AddHandlerValues} "$0\snews"  "$2" "$8,0" "${AppRegNameNews} URL" "true" ""
 !macroend
-!define SetHandlers "!insertmacro SetHandlers"
+!define SetHandlersNews "!insertmacro SetHandlersNews"
+
 ; XXXrstrong - there are several values that will be overwritten by and
 ; overwrite other installs of the same application.
 !macro SetStartMenuInternet
   GetFullPathName $8 "$INSTDIR\${FileMainEXE}"
   GetFullPathName $7 "$INSTDIR\uninstall\helper.exe"
 
   ${StrFilter} "${FileMainEXE}" "+" "" "" $R9
 
@@ -227,41 +426,44 @@
 
   WriteRegStr HKLM "$0\Capabilities\URLAssociations" "ftp"    "SeaMonkeyURL"
   WriteRegStr HKLM "$0\Capabilities\URLAssociations" "gopher" "SeaMonkeyURL"
   WriteRegStr HKLM "$0\Capabilities\URLAssociations" "http"   "SeaMonkeyURL"
   WriteRegStr HKLM "$0\Capabilities\URLAssociations" "https"  "SeaMonkeyURL"
 
   ; Vista Registered Application
   WriteRegStr HKLM "Software\RegisteredApplications" "${AppRegName}" "$0\Capabilities"
+!macroend
+!define SetStartMenuInternet "!insertmacro SetStartMenuInternet"
 
+!macro FixShellIconHandler
   ; The IconHandler reference for SeaMonkeyHTML can end up in an inconsistent
   ; state due to changes not being detected by the IconHandler for side by side
   ; installs. The symptoms can be either an incorrect icon or no icon being
   ; displayed for files associated with Firefox. By setting it here it will
   ; always reference the install referenced in the
   ; HKLM\Software\Classes\SeaMonkeyHTML registry key.
   ClearErrors
   ReadRegStr $2 HKLM "Software\Classes\SeaMonkeyHTML\ShellEx\IconHandler" ""
   ${Unless} ${Errors}
     ClearErrors
     ReadRegStr $3 HKLM "Software\Classes\CLSID\$2\Old Icon\SeaMonkeyHTML\DefaultIcon" ""
     ${Unless} ${Errors}
       WriteRegStr HKLM "Software\Classes\CLSID\$2\Old Icon\SeaMonkeyHTML\DefaultIcon" "" "$8,1"
     ${EndUnless}
   ${EndUnless}
 !macroend
-!define SetStartMenuInternet "!insertmacro SetStartMenuInternet"
+!define FixShellIconHandler "!insertmacro FixShellIconHandler"
 
 ; XXXrstrong - there are several values that will be overwritten by and
 ; overwrite other installs of the same application.
 !macro SetClientsMail
-  GetFullPathName $8 "$INSTDIR\${FileMainEXE}"
-  GetFullPathName $7 "$INSTDIR\uninstall\helper.exe"
-  GetFullPathName $6 "$INSTDIR\mozMapi32.dll"
+  ${GetLongPath} "$INSTDIR\${FileMainEXE}" $8
+  ${GetLongPath} "$INSTDIR\uninstall\helper.exe" $7
+  ${GetLongPath} "$INSTDIR\mozMapi32.dll" $6
 
   StrCpy $0 "Software\Clients\Mail\${BrandFullNameInternal}"
   WriteRegStr HKLM "$0" "" "${BrandFullNameInternal}"
   WriteRegStr HKLM "$0\DefaultIcon" "" "$8,0"
   WriteRegStr HKLM "$0" "DLLPath" "$6"
 
   ; MapiProxy.dll can be used by multiple applications but
   ; is only registered for the last application installed. When the last
@@ -293,16 +495,28 @@
   WriteRegStr HKLM "$1\MozillaMapi.1\CLSID" "" "{29F458BE-8866-11D5-A3DD-00B0D0F3BAA7}"
 
   ; The Reinstall Command is defined at
   ; http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/programmersguide/shell_adv/registeringapps.asp
   WriteRegStr HKLM "$0\InstallInfo" "HideIconsCommand" "$\"$7$\" /HideShortcuts"
   WriteRegStr HKLM "$0\InstallInfo" "ShowIconsCommand" "$\"$7$\" /ShowShortcuts"
   WriteRegStr HKLM "$0\InstallInfo" "ReinstallCommand" "$\"$7$\" /SetAsDefaultAppGlobal"
 
+  ClearErrors
+  ReadRegDWORD $1 HKLM "$0\InstallInfo" "IconsVisible"
+  ; If the IconsVisible name value pair doesn't exist add it otherwise the
+  ; application won't be displayed in Set Program Access and Defaults.
+  ${If} ${Errors}
+    ${If} ${FileExists} "$QUICKLAUNCH\${BrandFullName}.lnk"
+      WriteRegDWORD HKLM "$0\InstallInfo" "IconsVisible" 1
+    ${Else}
+      WriteRegDWORD HKLM "$0\InstallInfo" "IconsVisible" 0
+    ${EndIf}
+  ${EndIf}
+
   ; Mail shell/open/command
   WriteRegStr HKLM "$0\shell\open\command" "" "$\"$8$\" -mail"
 
   ; options
   WriteRegStr HKLM "$0\shell\properties" "" "$(CONTEXT_OPTIONS)"
   WriteRegStr HKLM "$0\shell\properties\command" "" "$\"$8$\" -options"
 
   ; safemode
@@ -318,25 +532,62 @@
   WriteRegStr HKLM "$0\Capabilities" "ApplicationIcon" "$8,0"
   WriteRegStr HKLM "$0\Capabilities" "ApplicationName" "${AppRegNameMail}"
   WriteRegStr HKLM "$0\Capabilities\FileAssociations" ".eml"   "SeaMonkeyEML"
   WriteRegStr HKLM "$0\Capabilities\StartMenu" "Mail" "${BrandFullNameInternal}"
   WriteRegStr HKLM "$0\Capabilities\URLAssociations" "mailto" "SeaMonkeyCOMPOSE"
 
   ; Vista Registered Application
   WriteRegStr HKLM "Software\RegisteredApplications" "${AppRegNameMail}" "$0\Capabilities"
+!macroend
+!define SetClientsMail "!insertmacro SetClientsMail"
 
-  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-  ; News
-  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; XXXrstrong - there are several values that will be overwritten by and
+; overwrite other installs of the same application.
+!macro SetClientsNews
+  ${GetLongPath} "$INSTDIR\${FileMainEXE}" $8
+  ${GetLongPath} "$INSTDIR\uninstall\helper.exe" $7
+  ${GetLongPath} "$INSTDIR\mozMapi32.dll" $6
+  
   StrCpy $0 "Software\Clients\News\${BrandFullNameInternal}"
   WriteRegStr HKLM "$0" "" "${BrandFullNameInternal}"
   WriteRegStr HKLM "$0\DefaultIcon" "" "$8,0"
   WriteRegStr HKLM "$0" "DLLPath" "$6"
 
+  ; MapiProxy.dll can exist in multiple installs of the application. Registration
+  ; occurs as follows with the last action to occur being the one that wins:
+  ; On install and software update when helper.exe runs with the /PostUpdate
+  ; argument. On setting the application as the system's default application 
+  ; using Window's "Set program access and defaults".
+
+  !ifndef NO_LOG
+    ${LogHeader} "DLL Registration"
+  !endif
+  ClearErrors
+  RegDLL "$INSTDIR\MapiProxy.dll"
+  !ifndef NO_LOG  
+    ${If} ${Errors}
+      ${LogMsg} "** ERROR Registering: $INSTDIR\MapiProxy.dll **"
+    ${Else}
+      ${LogUninstall} "DLLReg: \MapiProxy.dll"
+      ${LogMsg} "Registered: $INSTDIR\MapiProxy.dll"
+    ${EndIf}
+  !endif
+
+  StrCpy $1 "Software\Classes\CLSID\{29F458BE-8866-11D5-A3DD-00B0D0F3BAA7}"
+  WriteRegStr HKLM "$1\LocalServer32" "" "$\"$8$\" /MAPIStartup"
+  WriteRegStr HKLM "$1\ProgID" "" "MozillaMapi.1"
+  WriteRegStr HKLM "$1\VersionIndependentProgID" "" "MozillaMAPI"
+  StrCpy $1 "SOFTWARE\Classes"
+  WriteRegStr HKLM "$1\MozillaMapi" "" "Mozilla MAPI"
+  WriteRegStr HKLM "$1\MozillaMapi\CLSID" "" "{29F458BE-8866-11D5-A3DD-00B0D0F3BAA7}"
+  WriteRegStr HKLM "$1\MozillaMapi\CurVer" "" "MozillaMapi.1"
+  WriteRegStr HKLM "$1\MozillaMapi.1" "" "Mozilla MAPI"
+  WriteRegStr HKLM "$1\MozillaMapi.1\CLSID" "" "{29F458BE-8866-11D5-A3DD-00B0D0F3BAA7}"
+  
   ; Mail shell/open/command
   WriteRegStr HKLM "$0\shell\open\command" "" "$\"$8$\" -mail"
 
   ; Vista Capabilities registry keys
   WriteRegStr HKLM "$0\Capabilities" "ApplicationDescription" "$(REG_APP_DESC)"
   WriteRegStr HKLM "$0\Capabilities" "ApplicationIcon" "$8,0"
   WriteRegStr HKLM "$0\Capabilities" "ApplicationName" "${AppRegNameNews}"
   WriteRegStr HKLM "$0\Capabilities\URLAssociations" "nntp" "SeaMonkeyNEWS"
@@ -347,112 +598,200 @@
   StrCpy $1 "$\"$8$\" -mail $\"%1$\""
   ${AddHandlerValues} "$0\Protocols\nntp" "$1" "$8,0" "${AppRegNameNews} URL" "true" ""
   ${AddHandlerValues} "$0\Protocols\news" "$1" "$8,0" "${AppRegNameNews} URL" "true" ""
   ${AddHandlerValues} "$0\Protocols\snews" "$1" "$8,0" "${AppRegNameNews} URL" "true" ""
 
   ; Vista Registered Application
   WriteRegStr HKLM "Software\RegisteredApplications" "${AppRegNameNews}" "$0\Capabilities"
 !macroend
-!define SetClientsMail "!insertmacro SetClientsMail"
+!define SetClientsNews "!insertmacro SetClientsNews"
 
 !macro SetAppKeys
+  ${GetLongPath} "$INSTDIR" $8
   StrCpy $0 "Software\Mozilla\${BrandFullNameInternal}\${AppVersion} (${AB_CD})\Main"
-  ${WriteRegStr2} $TmpVal "$0" "Install Directory" "$INSTDIR" 0
-  ${WriteRegStr2} $TmpVal "$0" "PathToExe" "$INSTDIR\${FileMainEXE}" 0
+  ${WriteRegStr2} $TmpVal "$0" "Install Directory" "$8" 0
+  ${WriteRegStr2} $TmpVal "$0" "PathToExe" "$8\${FileMainEXE}" 0
   ${WriteRegStr2} $TmpVal "$0" "Program Folder Path" "$SMPROGRAMS\$StartMenuDir" 0
 
   SetShellVarContext all  ; Set $DESKTOP to All Users
   ${Unless} ${FileExists} "$DESKTOP\${BrandFullName}.lnk"
     SetShellVarContext current  ; Set $DESKTOP to the current user's desktop
   ${EndUnless}
 
   ${If} ${FileExists} "$DESKTOP\${BrandFullName}.lnk"
     ShellLink::GetShortCutArgs "$DESKTOP\${BrandFullName}.lnk"
     Pop $1
-    ${If} $1 == ""
+    ${If} "$1" == ""
       ShellLink::GetShortCutTarget "$DESKTOP\${BrandFullName}.lnk"
       Pop $1
-      ; Needs to handle short paths
-      ${If} $1 == "$INSTDIR\${FileMainEXE}"
+      ${GetLongPath} "$1" $1
+      ${If} "$1" == "$8\{FileMainEXE}"
         ${WriteRegDWORD2} $TmpVal "$0" "Create Desktop Shortcut" 1 0
       ${Else}
         ${WriteRegDWORD2} $TmpVal "$0" "Create Desktop Shortcut" 0 0
       ${EndIf}
     ${EndIf}
   ${EndIf}
 
   ; XXXrstrong - need a cleaner way to prevent unsetting SHCTX from HKLM when
   ; trying to find the desktop shortcut.
-  ${If} $TmpVal == "HKCU"
+  ${If} "$TmpVal" == "HKCU"
     SetShellVarContext current
   ${Else}
     SetShellVarContext all
   ${EndIf}
 
   ${If} ${FileExists} "$QUICKLAUNCH\${BrandFullName}.lnk"
     ShellLink::GetShortCutArgs "$QUICKLAUNCH\${BrandFullName}.lnk"
     Pop $1
-    ${If} $1 == ""
+    ${If} "$1" == ""
       ShellLink::GetShortCutTarget "$QUICKLAUNCH\${BrandFullName}.lnk"
       Pop $1
-      ; Needs to handle short paths
-      ${If} $1 == "$INSTDIR\${FileMainEXE}"
+      ${GetLongPath} "$1" $1
+      ${If} "$1" == "$8\${FileMainEXE}"
         ${WriteRegDWORD2} $TmpVal "$0" "Create Quick Launch Shortcut" 1 0
       ${Else}
         ${WriteRegDWORD2} $TmpVal "$0" "Create Quick Launch Shortcut" 0 0
       ${EndIf}
     ${EndIf}
   ${EndIf}
   ; XXXrstrong - "Create Start Menu Shortcut" and "Start Menu Folder" are only
   ; set in the installer and should also be set here for software update.
 
   StrCpy $0 "Software\Mozilla\${BrandFullNameInternal}\${AppVersion} (${AB_CD})\Uninstall"
-  ${WriteRegStr2} $TmpVal "$0" "Uninstall Log Folder" "$INSTDIR\uninstall" 0
+  ${WriteRegStr2} $TmpVal "$0" "Uninstall Log Folder" "$8\uninstall" 0
   ${WriteRegStr2} $TmpVal "$0" "Description" "${BrandFullNameInternal} (${AppVersion})" 0
 
   StrCpy $0 "Software\Mozilla\${BrandFullNameInternal}\${AppVersion} (${AB_CD})"
   ${WriteRegStr2} $TmpVal  "$0" "" "${AppVersion} (${AB_CD})" 0
 
   StrCpy $0 "Software\Mozilla\${BrandFullNameInternal} ${AppVersion}\bin"
-  ${WriteRegStr2} $TmpVal "$0" "PathToExe" "$INSTDIR\${FileMainEXE}" 0
+  ${WriteRegStr2} $TmpVal "$0" "PathToExe" "$8\${FileMainEXE}" 0
 
   StrCpy $0 "Software\Mozilla\${BrandFullNameInternal} ${AppVersion}\extensions"
-  ${WriteRegStr2} $TmpVal "$0" "Components" "$INSTDIR\components" 0
-  ${WriteRegStr2} $TmpVal "$0" "Plugins" "$INSTDIR\plugins" 0
+  ${WriteRegStr2} $TmpVal "$0" "Components" "$8\components" 0
+  ${WriteRegStr2} $TmpVal "$0" "Plugins" "$8\plugins" 0
 
   StrCpy $0 "Software\Mozilla\${BrandFullNameInternal} ${AppVersion}"
   ${WriteRegStr2} $TmpVal "$0" "GeckoVer" "${GREVersion}" 0
 
   StrCpy $0 "Software\Mozilla\${BrandFullNameInternal}"
   ${WriteRegStr2} $TmpVal "$0" "" "${GREVersion}" 0
   ${WriteRegStr2} $TmpVal "$0" "CurrentVersion" "${AppVersion} (${AB_CD})" 0
 !macroend
 !define SetAppKeys "!insertmacro SetAppKeys"
 
 !macro SetUninstallKeys
+  StrCpy $0 "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal} (${AppVersion})"
+  ${GetLongPath} "$INSTDIR" $8
+
   ; Write the uninstall registry keys
-  StrCpy $0 "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal} (${AppVersion})"
-  GetFullPathName $8 "$INSTDIR\${FileMainEXE}"
-  GetFullPathName $7 "$INSTDIR\uninstall\helper.exe"
-
   ${WriteRegStr2} $TmpVal "$0" "Comments" "${BrandFullNameInternal}" 0
-  ${WriteRegStr2} $TmpVal "$0" "DisplayIcon" "$8,0" 0
+  ${WriteRegStr2} $TmpVal "$0" "DisplayIcon" "$8\${FileMainEXE},0" 0
   ${WriteRegStr2} $TmpVal "$0" "DisplayName" "${BrandFullNameInternal} (${AppVersion})" 0
   ${WriteRegStr2} $TmpVal "$0" "DisplayVersion" "${AppVersion} (${AB_CD})" 0
-  ${WriteRegStr2} $TmpVal "$0" "InstallLocation" "$INSTDIR" 0
+  ${WriteRegStr2} $TmpVal "$0" "InstallLocation" "$8" 0
   ${WriteRegStr2} $TmpVal "$0" "Publisher" "Mozilla" 0
-  ${WriteRegStr2} $TmpVal "$0" "UninstallString" "$7" 0
+  ${WriteRegStr2} $TmpVal "$0" "UninstallString" "$8\uninstall\helper.exe" 0
   ${WriteRegStr2} $TmpVal "$0" "URLInfoAbout" "${URLInfoAbout}" 0
   ${WriteRegStr2} $TmpVal "$0" "URLUpdateInfo" "${URLUpdateInfo}" 0
   ${WriteRegDWORD2} $TmpVal "$0" "NoModify" 1 0
   ${WriteRegDWORD2} $TmpVal "$0" "NoRepair" 1 0
 !macroend
 !define SetUninstallKeys "!insertmacro SetUninstallKeys"
 
+; Updates protocol handlers if their registry open command value is for this
+; install location
+!macro UpdateProtocolHandlers
+  ; Store the command to open the app with an url in a register for easy access.
+  ${GetLongPath} "$INSTDIR\${FileMainEXE}" $8
+  StrCpy $0 "SOFTWARE\Classes"
+  StrCpy $1 "$\"$8$\" -osint -compose $\"%1$\""
+  StrCpy $2 "$\"$8$\" -osint -mail $\"%1$\""
+  StrCpy $3 "$\"$8$\" -requestPending -osint -url $\"%1$\""
+  StrCpy $4 "$\"%1$\",,0,0,,,,"
+  StrCpy $5 "$\"$8$\" -url $\"%1$\""
+
+  ; Only set the file and protocol handlers if the existing one under HKCR is
+  ; for this install location.
+  ${IsHandlerForInstallDir} "SeaMonkeyHTML" $R9
+  ${If} "$R9" == "true"
+    ; An empty string is used for the 5th param because SeaMonkeyHTML is not a
+    ; protocol handler.
+    ${AddHandlerValues} "SeaMonkeyHTML" "$5" \
+                        "$INSTDIR\chrome\icons\default\html-file.ico" \
+                        "${AppRegName} Document" "" ""
+  ${EndIf}
+
+  ${IsHandlerForInstallDir} "SeaMonkeyURL" $R9
+  ${If} "$R9" == "true"
+    ${AddDDEHandlerValues} "SeaMonkeyURL" "$3" "$8,0" "${AppRegName} URL" \
+                           "true" "${DDEApplication}" "$4" "WWW_OpenURL"
+  ${EndIf}
+
+  ${IsHandlerForInstallDir} "ftp" $R9
+  ${If} "$R9" == "true"
+    ${AddDDEHandlerValues} "ftp" "$3" "$8,0" "" "" "${DDEApplication}" \
+                           "$4" "WWW_OpenURL"
+  ${EndIf}
+
+  ${IsHandlerForInstallDir} "http" $R9
+  ${If} "$R9" == "true"
+    ${AddDDEHandlerValues} "http" "$3" "$8,0" "" "" "${DDEApplication}" \
+                           "$4" "WWW_OpenURL"
+  ${EndIf}
+
+  ${IsHandlerForInstallDir} "https" $R9
+  ${If} "$R9" == "true"
+    ${AddDDEHandlerValues} "https" "$3" "$8,0" "" "" "${DDEApplication}" \
+                           "$4" "WWW_OpenURL"
+  ${EndIf}
+
+  ${IsHandlerForInstallDir} "SeaMonkeyEML" $R9
+  ${If} "$R9" == "true"
+    ${AddHandlerValues} "SOFTWARE\Classes\SeaMonkeyEML" "$2" \
+                        "$INSTDIR\chrome\icons\default\misc-file.ico" \
+                        "${AppRegNameMail} Document" "" ""
+  ${EndIf}
+
+  ${IsHandlerForInstallDir} "SeaMonkeyMAIL" $R9
+  ${If} "$R9" == "true"
+    ${AddHandlerValues} "SOFTWARE\Classes\SeaMonkeyMAIL" "$2" "$8,0" \
+                        "${AppRegNameMail} URL" "true" ""
+  ${EndIf}
+
+  ${IsHandlerForInstallDir} "mailto" $R9
+  ${If} "$R9" == "true"
+    ${AddHandlerValues} "SOFTWARE\Classes\mailto" "$1" "$8,0" "" "" ""
+  ${EndIf}
+
+  ${IsHandlerForInstallDir} "SeaMonkeyNEWS" $R9
+  ${If} "$R9" == "true"
+    ${AddHandlerValues} "SOFTWARE\Classes\SeaMonkeyNEWS" "$2" "$8,0" \
+                        "${AppRegNameMail} URL" "true" ""
+  ${EndIf}
+
+  ${IsHandlerForInstallDir} "news" $R9
+  ${If} "$R9" == "true"
+    ${AddHandlerValues} "SOFTWARE\Classes\news" "$2" "$8,0" "" "" ""
+  ${EndIf}
+
+  ${IsHandlerForInstallDir} "snews" $R9
+  ${If} "$R9" == "true"
+    ${AddHandlerValues} "SOFTWARE\Classes\snews" "$2" "$8,0" "" "" ""
+  ${EndIf}
+
+  ${IsHandlerForInstallDir} "nntp" $R9
+  ${If} "$R9" == "true"
+    ${AddHandlerValues} "SOFTWARE\Classes\nntp" "$2" "$8,0" "" "" ""
+  ${EndIf}
+!macroend
+!define UpdateProtocolHandlers "!insertmacro UpdateProtocolHandlers"
+
 !macro FixClassKeys
   StrCpy $0 "SOFTWARE\Classes"
 
   ; BROWSER part
   ; File handler keys and name value pairs that may need to be created during
   ; install or upgrade.
   ReadRegStr $2 SHCTX "$0\.shtml" "Content Type"
   ${If} $2 == ""
@@ -547,17 +886,17 @@
   GetFullPathName $2 "$3"
   ClearErrors
   ${WordFind} "$2" "${FileMainEXE}" "E+1{" $R1
   ${Unless} ${Errors}
    ${AddHandlerValues} "$0\mailto" "$1" "$8,0" "" "" ""
   ${EndUnless}
 
   StrCpy $1 "$\"$8$\" $\"%1$\""
-  ${AddHandlerValues} "$0\SeaMonkeyEML" "$1" "$8,0" "${AppRegNameMail} Document" "" ""
+  ${AddHandlerValues} "$0\SeaMonkeyEML" "$1" "$INSTDIR\chrome\icons\default\misc-file.ico" "${AppRegNameMail} Document" "" ""
 
   StrCpy $1 "$\"$8$\" -mail $\"%1$\""
   ${AddHandlerValues} "$0\SeaMonkeyNEWS" "$1" "$8,0" "${AppRegNameNews} URL" "true" ""
 
   ReadRegStr $2 SHCTX "$0\news\shell\open\command" ""
   ${GetPathFromString} "$2" $3
   GetFullPathName $2 "$3"
   ClearErrors
@@ -600,8 +939,66 @@
   ClearErrors
   ${WordFind} "$2" "${FileMainEXE}" "E+1{" $R1
   ${Unless} ${Errors}
     DeleteRegKey HKLM "$0\.eml\DefaultIcon"
   ${EndUnless}
 
 !macroend
 !define FixClassKeys "!insertmacro FixClassKeys"
+
+; The files to check if they are in use during (un)install so the restart is
+; required message is displayed. All files must be located in the $INSTDIR
+; directory.
+!macro PushFilesToCheck
+  ; The first string to be pushed onto the stack MUST be "end" to indicate
+  ; that there are no more files to check in $INSTDIR and the last string
+  ; should be ${FileMainEXE} so if it is in use the CheckForFilesInUse macro
+  ; returns after the first check.
+  Push "end"
+  Push "AccessibleMarshal.dll"
+  Push "freebl3.dll"
+  Push "nssckbi.dll"
+  Push "nspr4.dll"
+  Push "nssdbm3.dll"
+  Push "sqlite3.dll"
+  Push "xpcom.dll"
+  Push "crashreporter.exe"
+  Push "updater.exe"
+  Push "xpicleanup.exe"
+  Push "MapiProxy.dll"
+  Push "mozMapi32.dll"
+  Push "${FileMainEXE}"
+!macroend
+!define PushFilesToCheck "!insertmacro PushFilesToCheck"
+
+; The !ifdef NO_LOG prevents warnings when compiling the installer since these
+; functions are currently only used by the uninstaller.
+!ifdef NO_LOG
+Function SetAsDefaultMailAppUser
+  SetShellVarContext current  ; Set SHCTX to the current user (e.g. HKCU)
+  ${SetHandlersMail}
+  ${If} ${AtLeastWinVista}
+    ClearErrors
+    ReadRegStr $0 HKLM "Software\RegisteredApplications" "${AppRegNameMail}"
+    ; Only register as the handler on Vista if the app registry name exists
+    ; under the RegisteredApplications registry key.
+    ${Unless} ${Errors}
+      AppAssocReg::SetAppAsDefaultAll "${AppRegNameMail}"
+    ${EndUnless}
+  ${EndIf}
+FunctionEnd
+
+Function SetAsDefaultNewsAppUser
+  SetShellVarContext current  ; Set SHCTX to the current user (e.g. HKCU)
+  ${SetHandlersNews}
+  ${If} ${AtLeastWinVista}
+    ClearErrors
+    ReadRegStr $0 HKLM "Software\RegisteredApplications" "${AppRegNameNews}"
+    ; Only register as the handler on Vista if the app registry name exists
+    ; under the RegisteredApplications registry key.
+    ${Unless} ${Errors}
+      AppAssocReg::SetAppAsDefaultAll "${AppRegNameNews}"
+    ${EndUnless}
+  ${EndIf}
+FunctionEnd
+!endif
+
--- a/suite/installer/windows/nsis/uninstaller.nsi
+++ b/suite/installer/windows/nsis/uninstaller.nsi
@@ -31,79 +31,108 @@
 # decision by deleting the provisions above and replace them with the notice
 # and other provisions required by the GPL or the LGPL. If you do not delete
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK *****
 
 # Also requires:
-# ShellLink plugin http://nsis.sourceforge.net/ShellLink_plug-in
+# AppAssocReg http://nsis.sourceforge.net/Application_Association_Registration_plug-in
+# ShellLink   http://nsis.sourceforge.net/ShellLink_plug-in
+# UAC         http://nsis.sourceforge.net/UAC_plug-in
+
 
 ; Set verbosity to 3 (e.g. no script) to lessen the noise in the build logs
 !verbose 3
 
 ; 7-Zip provides better compression than the lzma from NSIS so we add the files
 ; uncompressed and use 7-Zip to create a SFX archive of it
 SetDatablockOptimize on
 SetCompress off
 CRCCheck on
 
+RequestExecutionLevel user
+
 !addplugindir ./
 
+; USE_UAC_PLUGIN is temporary until other apps have been updated to use the UAC plugin
+!define USE_UAC_PLUGIN
+
 ; prevents compiling of the reg write logging.
 !define NO_LOG
 
 Var TmpVal
 
 ; Other included files may depend upon these includes!
 ; The following includes are provided by NSIS.
 !include FileFunc.nsh
 !include LogicLib.nsh
+!include MUI.nsh
 !include TextFunc.nsh
 !include WinMessages.nsh
+!include WinVer.nsh
 !include WordFunc.nsh
-!include MUI.nsh
 
 !insertmacro GetOptions
 !insertmacro GetParameters
+!insertmacro GetParent
 !insertmacro StrFilter
 !insertmacro WordFind
-!insertmacro WordReplace
 
-!insertmacro un.LineFind
-!insertmacro un.TrimNewLines
+!insertmacro un.GetParent
 
 ; The following includes are custom.
 !include branding.nsi
 !include defines.nsi
 !include common.nsh
 !include locales.nsi
 !include version.nsh
 
 ; This is named BrandShortName helper because we use this for software update
 ; post update cleanup.
 VIAddVersionKey "FileDescription" "${BrandShortName} Helper"
+VIAddVersionKey "OriginalFilename" "helper.exe"
 
+!insertmacro AddDDEHandlerValues
+!insertmacro AddHandlerValues
+!insertmacro CleanVirtualStore
 !insertmacro GetLongPath
 !insertmacro GetPathFromString
-!insertmacro AddHandlerValues
+!insertmacro IsHandlerForInstallDir
 !insertmacro RegCleanMain
 !insertmacro RegCleanUninstall
-!insertmacro WriteRegStr2
+!insertmacro UnloadUAC
+!insertmacro WordReplace
 !insertmacro WriteRegDWORD2
+!insertmacro WriteRegStr2
 
+!insertmacro un.ChangeMUIHeaderImage
+!insertmacro un.CheckForFilesInUse
+!insertmacro un.CleanUpdatesDir
+!insertmacro un.CleanVirtualStore
 !insertmacro un.GetLongPath
+!insertmacro un.GetSecondInstallPath
+!insertmacro un.ManualCloseAppPrompt
+!insertmacro un.ParseUninstallLog
+!insertmacro un.RegCleanAppHandler
+!insertmacro un.RegCleanFileHandler
 !insertmacro un.RegCleanMain
+!insertmacro un.RegCleanProtocolHandler
 !insertmacro un.RegCleanUninstall
-!insertmacro un.CloseApp
-!insertmacro un.GetSecondInstallPath
+!insertmacro un.RemoveQuotesFromPath
 
 !include shared.nsh
 
+; Helper macros for ui callbacks. Insert these after shared.nsh
+!insertmacro OnEndCommon
+!insertmacro UninstallOnInitCommon
+
+!insertmacro un.OnEndCommon
+
 Name "${BrandFullName}"
 OutFile "helper.exe"
 InstallDirRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal} (${AppVersion})" "InstallLocation"
 InstallDir "$PROGRAMFILES\${BrandFullName}"
 ShowUnInstDetails nevershow
 
 ################################################################################
 # Modern User Interface - MUI
@@ -122,273 +151,234 @@ ShowUnInstDetails nevershow
 !else
 !define MUI_HEADERIMAGE_BITMAP wizHeader.bmp
 !endif
 
 /**
  * Uninstall Pages
  */
 ; Welcome Page
+!define MUI_PAGE_CUSTOMFUNCTION_PRE un.preWelcome
+!define MUI_PAGE_CUSTOMFUNCTION_LEAVE un.leaveWelcome
 !insertmacro MUI_UNPAGE_WELCOME
 
 ; Uninstall Confirm Page
-!insertmacro MUI_UNPAGE_CONFIRM
+UninstPage custom un.preConfirm un.leaveConfirm
 
 ; Remove Files Page
-!define MUI_PAGE_CUSTOMFUNCTION_PRE un.preInstFiles
 !insertmacro MUI_UNPAGE_INSTFILES
 
-; Finish Page
+; Don't setup the survey controls, functions, etc. when the application has
+; defined NO_UNINSTALL_SURVEY
+!ifndef NO_UNINSTALL_SURVEY
 !define MUI_PAGE_CUSTOMFUNCTION_PRE un.preFinish
 !define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED
 !define MUI_FINISHPAGE_SHOWREADME ""
-
-; Setup the survey controls, functions, etc. except when the application has
-; defined NO_UNINSTALL_SURVEY
-!ifndef NO_UNINSTALL_SURVEY
 !define MUI_FINISHPAGE_SHOWREADME_TEXT $(SURVEY_TEXT)
 !define MUI_FINISHPAGE_SHOWREADME_FUNCTION un.Survey
 !endif
 
 !insertmacro MUI_UNPAGE_FINISH
 
+; Use the default dialog for IDD_VERIFY for a simple Banner
+ChangeUI IDD_VERIFY "${NSISDIR}\Contrib\UIs\default.exe"
+
 ################################################################################
 # Install Sections
 ; Empty section required for the installer to compile as an uninstaller
 Section ""
 SectionEnd
 
 ################################################################################
 # Uninstall Sections
 
 Section "Uninstall"
   SetDetailsPrint textonly
   DetailPrint $(STATUS_UNINSTALL_MAIN)
   SetDetailsPrint none
 
-  ; Remove registry entries for non-existent apps and for apps that point to our
-  ; install location in the Software\Mozilla key and uninstall registry entries
-  ; that point to our install location for both HKCU and HKLM.
-  SetShellVarContext current  ; Sets SHCTX to HKCU
+  ; Delete the app exe to prevent launching the app while we are uninstalling.
+  ClearErrors
+  ${DeleteFile} "$INSTDIR\${FileMainEXE}"
+  ${If} ${Errors}
+    ; If the user closed the application it can take several seconds for it to
+    ; shut down completely. If the application is being used by another user we
+    ; can still delete the files when the system is restarted.
+    Sleep 5000
+    ${DeleteFile} "$INSTDIR\${FileMainEXE}"
+    ClearErrors
+  ${EndIf}
+
+  SetShellVarContext current  ; Set SHCTX to HKCU
   ${un.RegCleanMain} "Software\Mozilla"
   ${un.RegCleanUninstall}
 
-  SetShellVarContext all  ; Sets SHCTX to HKLM
-  ${un.RegCleanMain} "Software\Mozilla"
-  ${un.RegCleanUninstall}
+  ClearErrors
+  WriteRegStr HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" "Write Test"
+  ${If} ${Errors}
+    StrCpy $TmpVal "HKCU" ; used primarily for logging
+  ${Else}
+    SetShellVarContext all  ; Set SHCTX to HKLM
+    DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest"
+    StrCpy $TmpVal "HKLM" ; used primarily for logging
+    ${un.RegCleanMain} "Software\Mozilla"
+    ${un.RegCleanUninstall}
+  ${EndIf}
+
+  ${un.RegCleanAppHandler} "SeaMonkeyURL"
+  ${un.RegCleanAppHandler} "SeaMonkeyHTML"
+  ${un.RegCleanAppHandler} "SeaMonkeyMAIL"
+  ${un.RegCleanAppHandler} "SeaMonkeyNEWS"
+  ${un.RegCleanAppHandler} "SeaMonkeyEML"
+  ${un.RegCleanProtocolHandler} "http"
+  ${un.RegCleanProtocolHandler} "https"
+  ${un.RegCleanProtocolHandler} "ftp"
+  ${un.RegCleanProtocolHandler} "mailto"
+  ${un.RegCleanProtocolHandler} "news"
+  ${un.RegCleanProtocolHandler} "nntp"
+  ${un.RegCleanProtocolHandler} "snews"
+
+  ClearErrors
+  ReadRegStr $R9 HKCR "SeaMonkeyEML" ""
+  ; Don't clean up the file handlers if the SeaMonkeyEML key still exists since
+  ; there could be a second installation that may be the default file handler
+  ${If} ${Errors}
+    ${un.RegCleanFileHandler}  ".eml"   "SeaMonkeyEML"
+  ${EndIf}
+
+  ClearErrors
+  ReadRegStr $R9 HKCR "SeaMonkeyHTML" ""
+  ; Don't clean up the file handlers if the SeaMonkeyHTML key still exists since
+  ; there could be a second installation that may be the default file handler
+  ${If} ${Errors}
+    ${un.RegCleanFileHandler}  ".htm"   "SeaMonkeyHTML"
+    ${un.RegCleanFileHandler}  ".html"  "SeaMonkeyHTML"
+    ${un.RegCleanFileHandler}  ".shtml" "SeaMonkeyHTML"
+    ${un.RegCleanFileHandler}  ".xht"   "SeaMonkeyHTML"
+    ${un.RegCleanFileHandler}  ".xhtml" "SeaMonkeyHTML"
+  ${EndIf}
 
   SetShellVarContext all  ; Set SHCTX to HKLM
   ${un.GetSecondInstallPath} "Software\Mozilla" $R9
   ${If} $R9 == "false"
     SetShellVarContext current  ; Set SHCTX to HKCU
     ${un.GetSecondInstallPath} "Software\Mozilla" $R9
   ${EndIf}
 
   StrCpy $0 "Software\Clients\StartMenuInternet\${FileMainEXE}\shell\open\command"
-  ReadRegStr $1 HKLM "$0" ""
-  Push $1
-  ${GetPathFromRegStr}
-  Pop $R0
-  Push $R0
-  ${GetParentDir}
-  Pop $R1
+  ReadRegStr $R1 HKLM "$0" ""
+  ${un.RemoveQuotesFromPath} "$R1" $R1
+  ${un.GetParent} "$R1" $R1
 
   ; Only remove the StartMenuInternet key if it refers to this install location.
   ; The StartMenuInternet registry key is independent of the default browser
   ; settings. The XPInstall base un-installer always removes this key if it is
   ; uninstalling the default browser and it will always replace the keys when
   ; installing even if there is another install of SeaMonkey that is set as the
   ; default browser. Now the key is always updated on install but it is only
   ; removed if it refers to this install location.
   ${If} "$INSTDIR" == "$R1"
-    ; XXXrstrong - if there is another installation of the same app ideally we
-    ; would just modify these values. The GetSecondInstallPath macro could be
-    ; made to provide enough information to do this.
     DeleteRegKey HKLM "Software\Clients\StartMenuInternet\${FileMainEXE}"
     DeleteRegValue HKLM "Software\RegisteredApplications" "${AppRegName}"
   ${EndIf}
 
   StrCpy $0 "Software\Clients\Mail\${BrandFullNameInternal}\shell\open\command"
-  ReadRegStr $1 HKLM "$0" ""
-  Push $1
-  ${GetPathFromRegStr}
-  Pop $R0
-  Push $R0
-  ${GetParentDir}
-  Pop $R1
+  ReadRegStr $R1 HKLM "$0" ""
+  ${un.RemoveQuotesFromPath} "$R1" $R1
+  ${un.GetParent} "$R1" $R1
 
   ; Only remove the Clients\Mail and Clients\News key if it refers to this
   ; install location. The Clients\Mail & Clients\News keys are independent
   ; of the default app for the OS settings. The XPInstall base un-installer
   ; always removes these keys if it is uninstalling the default app and it
   ; will always replace the keys when installing even if there is another
   ; install of SeaMonkey that is set as the default app. Now the keys are always
   ; updated on install but are only removed if they refer to this install
   ; location.
   ${If} "$INSTDIR" == "$R1"
-    ; XXXrstrong - if there is another installation of the same app ideally we
-    ; would just modify these values. The GetSecondInstallPath macro could be
-    ; made to provide enough information to do this.
     DeleteRegKey HKLM "Software\Clients\Mail\${BrandFullNameInternal}"
     DeleteRegKey HKLM "Software\Clients\News\${BrandFullNameInternal}"
     DeleteRegValue HKLM "Software\RegisteredApplications" "${AppRegNameMail}"
     DeleteRegValue HKLM "Software\RegisteredApplications" "${AppRegNameNews}"
   ${EndIf}
 
   StrCpy $0 "Software\Microsoft\Windows\CurrentVersion\App Paths\${FileMainEXE}"
   ${If} $R9 == "false"
     DeleteRegKey HKLM "$0"
     DeleteRegKey HKCU "$0"
     StrCpy $0 "Software\Microsoft\MediaPlayer\ShimInclusionList\${FileMainEXE}"
     DeleteRegKey HKLM "$0"
     DeleteRegKey HKCU "$0"
   ${Else}
-    ReadRegStr $1 HKLM "$0" ""
-    Push $1
-    ${GetPathFromRegStr}
-    Pop $R0
-    Push $R0
-    ${GetParentDir}
-    Pop $R1
+    ReadRegStr $R1 HKLM "$0" ""
+    ${un.RemoveQuotesFromPath} "$R1" $R1
+    ${un.GetParent} "$R1" $R1
     ${If} "$INSTDIR" == "$R1"
       WriteRegStr HKLM "$0" "" "$R9"
-      Push $R9
-      ${GetParentDir}
-      Pop $R1
+      ${un.GetParent} "$R9" $R1
       WriteRegStr HKLM "$0" "Path" "$R1"
     ${EndIf}
   ${EndIf}
 
-  ; Remove files. If we don't have a log file skip
-  ${If} ${FileExists} "$INSTDIR\uninstall\uninstall.log"
-    ; Copy the uninstall log file to a temporary file
-    GetTempFileName $TmpVal
-    CopyFiles "$INSTDIR\uninstall\uninstall.log" "$TmpVal"
-
-    ; Unregister DLL's
-    ${un.LineFind} "$TmpVal" "/NUL" "1:-1" "un.UnRegDLLsCallback"
-
-    ; Delete files
-    ${un.LineFind} "$TmpVal" "/NUL" "1:-1" "un.RemoveFilesCallback"
-
-    ; Remove directories we always control
-    RmDir /r "$INSTDIR\uninstall"
-    RmDir /r "$INSTDIR\updates"
-    RmDir /r "$INSTDIR\defaults\shortcuts"
-
-    ; Remove empty directories
-    ${un.LineFind} "$TmpVal" "/NUL" "1:-1" "un.RemoveDirsCallback"
-
-    ; Delete the temporary uninstall log file
-    ${DeleteFile} "$TmpVal"
-
-    ; Remove the installation directory if it is empty
-    ${RemoveDir} "$INSTDIR"
+  ; Remove directories and files we always control before parsing the uninstall
+  ; log so empty directories can be removed.
+  ${If} ${FileExists} "$INSTDIR\updates"
+    RmDir /r /REBOOTOK "$INSTDIR\updates"
+  ${EndIf}
+  ${If} ${FileExists} "$INSTDIR\defaults\shortcuts"
+    RmDir /r /REBOOTOK "$INSTDIR\defaults\shortcuts"
+  ${EndIf}
+  ${If} ${FileExists} "$INSTDIR\distribution"
+    RmDir /r /REBOOTOK "$INSTDIR\distribution"
+  ${EndIf}
+  ${If} ${FileExists} "$INSTDIR\removed-files"
+    Delete /REBOOTOK "$INSTDIR\removed-files"
   ${EndIf}
 
+  ; Remove the updates directory for Vista and above
+  ${un.CleanUpdatesDir} "Mozilla\SeaMonkey"
+
+  ; Remove files that may be left behind by the application in the
+  ; VirtualStore directory.
+  ${un.CleanVirtualStore}
+
+  ; Parse the uninstall log to unregister dll's and remove all installed
+  ; files / directories this install is responsible for.
+  ${un.ParseUninstallLog}
+
+  ; Remove the uninstall directory that we control
+  RmDir /r /REBOOTOK "$INSTDIR\uninstall"
+
+  ; Remove the installation directory if it is empty
+  ${RemoveDir} "$INSTDIR"
+
+  ; If seamonkey.exe was successfully deleted yet we still need to restart to
+  ; remove other files create a dummy seamonkey.exe.moz-delete to prevent the
+  ; installer from allowing an install without restart when it is required
+  ; to complete an uninstall.
+  ${If} ${RebootFlag}
+    ${Unless} ${FileExists} "$INSTDIR\${FileMainEXE}.moz-delete"
+      FileOpen $0 "$INSTDIR\${FileMainEXE}.moz-delete" w
+      FileWrite $0 "Will be deleted on restart"
+      Delete /REBOOTOK "$INSTDIR\${FileMainEXE}.moz-delete"
+      FileClose $0
+    ${EndUnless}
+  ${EndIf}
+
+
   ; Refresh desktop icons otherwise the start menu internet item won't be
-  ; removed and other ugly things will happen like recreation of the registry
-  ; key by the OS under some conditions.
+  ; removed and other ugly things will happen like recreation of the app's
+  ; clients registry key by the OS under some conditions.
   System::Call "shell32::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)"
 SectionEnd
 
 ################################################################################
 # Helper Functions
 
-Function un.RemoveFilesCallback
-  ${un.TrimNewLines} "$R9" "$R9"
-  StrCpy $R1 "$R9" 5
-  ${If} $R1 == "File:"
-    StrCpy $R9 "$R9" "" 6
-    StrCpy $R0 "$R9" 1
-    ; If the path is relative prepend the install directory
-    ${If} $R0 == "\"
-      StrCpy $R0 "$INSTDIR$R9"
-    ${Else}
-      StrCpy $R0 "$R9"
-    ${EndIf}
-    ${If} ${FileExists} "$R0"
-      ${DeleteFile} "$R0"
-    ${EndIf}
-  ${EndIf}
-  ClearErrors
-  Push 0
-FunctionEnd
-
-; Using locate will leave file handles open to some of the directories which
-; will prevent the deletion of these directories. This parses the uninstall.log
-; and uses the file entries to find / remove empty directories.
-Function un.RemoveDirsCallback
-  ${un.TrimNewLines} "$R9" "$R9"
-  StrCpy $R1 "$R9" 5
-  ${If} $R1 == "File:"
-    StrCpy $R9 "$R9" "" 6
-    StrCpy $R1 "$R9" 1
-    ${If} $R1 == "\"
-      StrCpy $R2 "$INSTDIR"
-      StrCpy $R1 "$INSTDIR$R9"
-    ${Else}
-      StrCpy $R2 ""
-      StrCpy $R1 "$R9"
-    ${EndIf}
-    loop:
-      Push $R1
-      ${GetParentDir}
-      Pop $R0
-      GetFullPathName $R1 "$R0"
-      ; We only try to remove empty directories but the Desktop, StartMenu, and
-      ; QuickLaunch directories can be empty so guard against removing them.
-      ${If} "$R2" != "$INSTDIR"
-        SetShellVarContext all
-        ${If} $R1 == "$DESKTOP"
-        ${OrIf} $R1 == "$STARTMENU"
-          GoTo end
-        ${EndIf}
-        SetShellVarContext current
-        ${If} $R1 == "$QUICKLAUNCH"
-        ${OrIf} $R1 == "$DESKTOP"
-        ${OrIf} $R1 == "$STARTMENU"
-          GoTo end
-        ${EndIf}
-      ${ElseIf} "$R1" == "$INSTDIR"
-        GoTo end
-      ${EndIf}
-      ${If} ${FileExists} "$R1"
-        RmDir "$R1"
-      ${EndIf}
-      ${If} ${Errors}
-      ${OrIf} "$R2" != "$INSTDIR"
-        GoTo end
-      ${EndIf}
-      GoTo loop
-  ${EndIf}
-
-  end:
-    ClearErrors
-    Push 0
-FunctionEnd
-
-Function un.UnRegDLLsCallback
-  ${un.TrimNewLines} "$R9" "$R9"
-  StrCpy $R1 "$R9" 7
-  ${If} $R1 == "DLLReg:"
-    StrCpy $R9 "$R9" "" 8
-    StrCpy $R1 "$R9" 1
-    ${If} $R1 == "\"
-      StrCpy $R1 "$INSTDIR$R9"
-    ${Else}
-      StrCpy $R1 "$R9"
-    ${EndIf}
-    UnRegDLL $R1
-  ${EndIf}
-  ClearErrors
-  Push 0
-FunctionEnd
-
-; Setup the survey controls, functions, etc. except when the application has
+; Don't setup the survey controls, functions, etc. when the application has
 ; defined NO_UNINSTALL_SURVEY
 !ifndef NO_UNINSTALL_SURVEY
 Function un.Survey
   Exec "$\"$TmpVal$\" $\"${SurveyURL}$\""
 FunctionEnd
 !endif
 
 ################################################################################
@@ -401,150 +391,168 @@ FunctionEnd
 !include "customLocale.nsh"
 !verbose pop
 
 ; Set this after the locale files to override it if it is in the locale. Using
 ; " " for BrandingText will hide the "Nullsoft Install System..." branding.
 BrandingText " "
 
 ################################################################################
-# Page pre and leave functions
+# Page pre, show, and leave functions
 
-; Checks if the app being uninstalled is running.
-Function un.preInstFiles
-  ; Try to delete the app executable and if we can't delete it try to close the
-  ; app. This allows running an instance that is located in another directory.
-  ClearErrors
-  ${If} ${FileExists} "$INSTDIR\${FileMainEXE}"
-    ${DeleteFile} "$INSTDIR\${FileMainEXE}"
+Function un.preWelcome
+  ${If} ${FileExists} "$INSTDIR\distribution\modern-wizard.bmp"
+    Delete "$PLUGINSDIR\modern-wizard.bmp"
+    CopyFiles /SILENT "$INSTDIR\distribution\modern-wizard.bmp" "$PLUGINSDIR\modern-wizard.bmp"
   ${EndIf}
-  ${If} ${Errors}
-    ClearErrors
-    ${un.CloseApp} "true" $(WARN_APP_RUNNING_UNINSTALL)
-    ; Delete the app exe to prevent launching the app while we are uninstalling.
-    ClearErrors
-    ${DeleteFile} "$INSTDIR\${FileMainEXE}"
-    ${If} ${Errors}
-      ClearErrors
-      ${un.CloseApp} "true" $(WARN_APP_RUNNING_UNINSTALL)
-      ClearErrors
-      ${DeleteFile} "$INSTDIR\${FileMainEXE}"
+FunctionEnd
+
+Function un.leaveWelcome
+  ${If} ${FileExists} "$INSTDIR\${FileMainEXE}"
+    Banner::show /NOUNLOAD "$(BANNER_CHECK_EXISTING)"
+
+    ${If} "$TmpVal" == "FoundMessageWindow"
+      Sleep 5000
+    ${EndIf}
+
+    ${PushFilesToCheck}
+
+    ${un.CheckForFilesInUse} $TmpVal
+
+    Banner::destroy
+
+    ${If} "$TmpVal" == "true"
+      StrCpy $TmpVal "FoundMessageWindow"
+      ${un.ManualCloseAppPrompt} "${WindowClass}" "$(WARN_MANUALLY_CLOSE_APP_UNINSTALL)"
+      StrCpy $TmpVal "true"
     ${EndIf}
   ${EndIf}
 FunctionEnd
 
-; When we add an optional action to the finish page the cancel button is
-; enabled. This disables it and leaves the finish button as the only choice.
-Function un.preFinish
-  !insertmacro MUI_INSTALLOPTIONS_WRITE "ioSpecial.ini" "settings" "cancelenabled" "0"
+Function un.preConfirm
+  ${If} ${FileExists} "$INSTDIR\distribution\modern-header.bmp"
+  ${AndIf} $hHeaderBitmap == ""
+    Delete "$PLUGINSDIR\modern-header.bmp"
+    CopyFiles /SILENT "$INSTDIR\distribution\modern-header.bmp" "$PLUGINSDIR\modern-header.bmp"
+    ${un.ChangeMUIHeaderImage} "$PLUGINSDIR\modern-header.bmp"
+  ${EndIf}
+
+  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Settings" NumFields "3"
+
+  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 1" Type   "label"
+  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 1" Text   "$(UN_CONFIRM_UNINSTALLED_FROM)"
+  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 1" Left   "0"
+  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 1" Right  "-1"
+  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 1" Top    "5"
+  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 1" Bottom "15"
+
+  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 2" Type   "text"
+  ; The contents of this control must be set as follows in the pre function
+  ; ${MUI_INSTALLOPTIONS_READ} $1 "unconfirm.ini" "Field 2" "HWND"
+  ; SendMessage $1 ${WM_SETTEXT} 0 "STR:$INSTDIR"
+  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 2" State  ""
+  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 2" Left   "0"
+  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 2" Right  "-1"
+  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 2" Top    "17"
+  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 2" Bottom "30"
+  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 2" flags  "READONLY"
+
+  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Type   "label"
+  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Text   "$(UN_CONFIRM_CLICK)"
+  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Left   "0"
+  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Right  "-1"
+  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Top    "130"
+  WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Bottom "150"
 
-  ; Setup the survey controls, functions, etc. except when the application has
-  ; defined NO_UNINSTALL_SURVEY
-  !ifdef NO_UNINSTALL_SURVEY
-    !insertmacro MUI_INSTALLOPTIONS_WRITE "ioSpecial.ini" "settings" "NumFields" "3"
-  !else
+  ${If} "$TmpVal" == "true"
+    WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" Type   "label"
+    WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" Text   "$(SUMMARY_REBOOT_REQUIRED_UNINSTALL)"
+    WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" Left   "0"
+    WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" Right  "-1"
+    WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" Top    "35"
+    WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" Bottom "45"
+
+    WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Settings" NumFields "4"
+  ${EndIf}
+
+  !insertmacro MUI_HEADER_TEXT "$(UN_CONFIRM_PAGE_TITLE)" "$(UN_CONFIRM_PAGE_SUBTITLE)"
+  ; The Summary custom page has a textbox that will automatically receive
+  ; focus. This sets the focus to the Install button instead.
+  !insertmacro MUI_INSTALLOPTIONS_INITDIALOG "unconfirm.ini"
+  GetDlgItem $0 $HWNDPARENT 1
+  System::Call "user32::SetFocus(i r0, i 0x0007, i,i)i"
+  ${MUI_INSTALLOPTIONS_READ} $1 "unconfirm.ini" "Field 2" "HWND"
+  SendMessage $1 ${WM_SETTEXT} 0 "STR:$INSTDIR"
+  !insertmacro MUI_INSTALLOPTIONS_SHOW
+FunctionEnd
+
+Function un.leaveConfirm
+  ; Try to delete the app executable and if we can't delete it try to find the
+  ; app's message window and prompt the user to close the app. This allows
+  ; running an instance that is located in another directory. If for whatever
+  ; reason there is no message window we will just rename the app's files and
+  ; then remove them on restart if they are in use.
+  ClearErrors
+  ${DeleteFile} "$INSTDIR\${FileMainEXE}"
+  ${If} ${Errors}
+    ${un.ManualCloseAppPrompt} "${WindowClass}" "$(WARN_MANUALLY_CLOSE_APP_UNINSTALL)"
+  ${EndIf}
+FunctionEnd
+
+!ifndef NO_UNINSTALL_SURVEY
+Function un.preFinish
+  ; Do not modify the finish page if there is a reboot pending
+  ${Unless} ${RebootFlag}
+    ; Setup the survey controls, functions, etc.
     StrCpy $TmpVal "SOFTWARE\Microsoft\IE Setup\Setup"
     ClearErrors
     ReadRegStr $0 HKLM $TmpVal "Path"
     ${If} ${Errors}
       !insertmacro MUI_INSTALLOPTIONS_WRITE "ioSpecial.ini" "settings" "NumFields" "3"
     ${Else}
       ExpandEnvStrings $0 "$0" ; this value will usually contain %programfiles%
       ${If} $0 != "\"
         StrCpy $0 "$0\"
       ${EndIf}
       StrCpy $0 "$0\iexplore.exe"
       ClearErrors
       GetFullPathName $TmpVal $0
       ${If} ${Errors}
         !insertmacro MUI_INSTALLOPTIONS_WRITE "ioSpecial.ini" "settings" "NumFields" "3"
+      ${Else}
+        ; When we add an optional action to the finish page the cancel button
+        ; is enabled. This disables it and leaves the finish button as the
+        ; only choice.
+        !insertmacro MUI_INSTALLOPTIONS_WRITE "ioSpecial.ini" "settings" "cancelenabled" "0"
       ${EndIf}
     ${EndIf}
-  !endif
 FunctionEnd
+!endif
 
 ################################################################################
 # Initialization Functions
 
 Function .onInit
-  GetFullPathName $INSTDIR "$EXEDIR\.."
-  ${Unless} ${FileExists} "$INSTDIR\${FileMainEXE}"
-    Abort
-  ${EndUnless}
-  ${GetParameters} $R0
-
-  ${Switch} $R0
-    ${Case} "/HideShortcuts"
-      ${HideShortcuts}
-      StrCpy $R1 "true"
-      ${Break}
-    ${Case} "/ShowShortcuts"
-      ${ShowShortcuts}
-      StrCpy $R1 "true"
-      ${Break}
-    ${Case} "/SetAsDefaultAppUser"
-      ${SetAsDefaultAppUser}
-      StrCpy $R1 "true"
-      ${Break}
-    ${Case} "/SetAsDefaultAppGlobal"
-      ${SetAsDefaultAppGlobal}
-      StrCpy $R1 "true"
-      ${Break}
-    ${Default}
-      ClearErrors
-      ${Unless} "$R0" == ""
-        ${WordReplace} "$R0" "$\"" "" "+" $R0
-        ClearErrors
-        ${GetOptions} "$R0" "/PostUpdate" $R2
-        ${Unless} ${Errors}
-          ${PostUpdate}
-          ClearErrors
-          ${GetOptions} "$R0" "/UninstallLog=" $R2
-          ${Unless} ${Errors}
-            ${Unless} "$R2" == ""
-              GetFullPathName $R3 "$R2"
-              ${If} ${FileExists} "$R3"
-                Delete "$INSTDIR\uninstall\*wizard*"
-                Delete "$INSTDIR\uninstall\uninstall.log"
-                CopyFiles /SILENT "$R3" "$INSTDIR\uninstall\"
-                Push $R3
-                ${GetParentDir}
-                Pop $R4
-                Delete "$R3"
-                RmDir "$R4"
-              ${EndIf}
-            ${EndUnless}
-          ${EndUnless}
-          StrCpy $R1 "true"
-        ${EndUnless}
-      ${EndUnless}
-      ${Break}
-  ${EndSwitch}
-
-  ${If} $R1 == "true"
-    System::Call "shell32::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)"
-    Quit
-  ${EndIf}
-
-  ; If we made it this far then this installer is being used as an uninstaller.
-  WriteUninstaller "$EXEDIR\uninstaller.exe"
-
-  ${If} $R0 == "/S"
-    StrCpy $TmpVal "$\"$EXEDIR\uninstaller.exe$\" /S"
-  ${Else}
-    StrCpy $TmpVal "$\"$EXEDIR\uninstaller.exe$\""
-  ${EndIf}
-
-  ; When the uninstaller is launched it copies itself to the temp directory so
-  ; it won't be in use so it can delete itself.
-  ExecWait $TmpVal
-  ${DeleteFile} "$EXEDIR\uninstaller.exe"
-  SetErrorLevel 0
-  Quit
+  ${UninstallOnInitCommon}
 FunctionEnd
 
 Function un.onInit
   GetFullPathName $INSTDIR "$INSTDIR\.."
+  ${un.GetLongPath} "$INSTDIR" $INSTDIR
   ${Unless} ${FileExists} "$INSTDIR\${FileMainEXE}"
     Abort
   ${EndUnless}
+
   StrCpy $LANGUAGE 0
+
+  ; Initialize $hHeaderBitmap to prevent redundant changing of the bitmap if
+  ; the user clicks the back button
+  StrCpy $hHeaderBitmap ""
 FunctionEnd
+
+Function .onGUIEnd
+  ${OnEndCommon}
+FunctionEnd
+
+Function un.onGUIEnd
+  ${un.OnEndCommon}
+FunctionEnd
+
--- a/suite/locales/en-US/installer/windows/custom.properties
+++ b/suite/locales/en-US/installer/windows/custom.properties
@@ -70,33 +70,48 @@ PROFILE_TEXT=Profile Manager
 OPTIONS_PAGE_TITLE=Setup Type
 OPTIONS_PAGE_SUBTITLE=Choose setup options
 SHORTCUTS_PAGE_TITLE=Set Up Shortcuts
 SHORTCUTS_PAGE_SUBTITLE=Create Program Icons
 SUMMARY_PAGE_TITLE=Summary
 SUMMARY_PAGE_SUBTITLE=Ready to start installing ${BrandShortName}
 SUMMARY_INSTALLED_TO=${BrandShortName} will be installed to the following location:
 SUMMARY_CLICK=Click Install to continue.
+SUMMARY_REBOOT_REQUIRED_INSTALL=A restart of your computer may be required to complete the installation.
+SUMMARY_REBOOT_REQUIRED_UNINSTALL=A restart of your computer may be required to complete the uninstall.
 SURVEY_TEXT=&Tell us what you thought of ${BrandShortName}
 LAUNCH_TEXT=&Launch ${BrandFullName} now
-WARN_APP_RUNNING_INSTALL=${BrandFullName} must be closed to proceed with the installation.\n\nClick "OK" to exit ${BrandFullName} automatically and continue.
-WARN_APP_RUNNING_UNINSTALL=${BrandFullName} must be closed to proceed with the uninstall.\n\nClick "OK" to exit ${BrandFullName} automatically and continue.
+WARN_MANUALLY_CLOSE_APP_LAUNCH=${BrandShortName} is already running.\n\nPlease close ${BrandShortName} prior to launching the version you have just installed.
+WARN_UNSUPPORTED_MSG=Sorry, ${BrandShortName} can't be installed. This version of ${BrandShortName} requires ${MinUnsupportedVer} or newer.
 CREATE_ICONS_DESC=Create icons for ${BrandShortName}:
 ICONS_DESKTOP=On my &Desktop
 ICONS_STARTMENU=In my &Start Menu Programs folder
 ICONS_QUICKLAUNCH=In my &Quick Launch bar
 WARN_WRITE_ACCESS=You don't have access to write to the installation directory.\n\nClick OK to select a different directory.
 WARN_DISK_SPACE=You don't have sufficient disk space to install to this location.\n\nClick OK to select a different location.
+WARN_MANUALLY_CLOSE_APP_INSTALL=${BrandShortName} must be closed to proceed with the installation.\n\nPlease close ${BrandShortName} to continue.
+WARN_MANUALLY_CLOSE_APP_UNINSTALL=${BrandShortName} must be closed to proceed with the uninstall.\n\nPlease close ${BrandShortName} to continue.
+WARN_RESTART_REQUIRED_UNINSTALL=Your computer must be restarted to complete a previous uninstall of ${BrandShortName}. Do you want to reboot now?
+WARN_RESTART_REQUIRED_UPGRADE=Your computer must be restarted to complete a previous upgrade of ${BrandShortName}. Do you want to reboot now?
+ERROR_CREATE_DIRECTORY_PREFIX=Error creating directory:
+ERROR_CREATE_DIRECTORY_SUFFIX=Click Cancel to stop the installation or\nRetry to try again.
+
+UN_CONFIRM_CLICK=Click Uninstall to continue.
+UN_CONFIRM_PAGE_TITLE=Uninstall ${BrandFullName}
+UN_CONFIRM_PAGE_SUBTITLE=Remove ${BrandFullName} from your computer.
+UN_CONFIRM_UNINSTALLED_FROM=${BrandShortName} will be uninstalled from the following location:
 
 STATUS_INSTALL_APP=Installing ${BrandShortName}…
 STATUS_INSTALL_LANG=Installing Language Files (${AB_CD})…
 STATUS_INSTALL_OPTIONAL=Installing Optional Components…
 STATUS_UNINSTALL_MAIN=Uninstalling ${BrandShortName}…
 STATUS_CLEANUP=A Little Housekeeping…
 
+BANNER_CHECK_EXISTING=Checking existing installation…
+
 # _DESC strings support approximately 65 characters per line.
 # One line
 OPTIONS_SUMMARY=Choose the type of setup you prefer, then click Next.
 # One line
 OPTION_STANDARD_DESC=${BrandShortName} will be installed with the most common options.
 OPTION_STANDARD_RADIO=&Standard
 # One line
 OPTION_COMPLETE_DESC=${BrandShortName} will be installed with all available options.