diff --git a/.gitignore b/.gitignore
index 26c12cc6920bd1b55a7ef5279614b97c206ceed0..903a02a8c9f314e50f8d6a5d769b83c3c7a3ab58 100755
--- a/.gitignore
+++ b/.gitignore
@@ -50,7 +50,7 @@ indra/newview/dbghelp.dll
 indra/newview/filters.xml
 indra/newview/fmod.dll
 indra/newview/fmod.log
-indra/newview/installers/windows/*
+indra/newview/installers/windows/*.ico
 indra/newview/mozilla-theme
 indra/newview/mozilla-universal-darwin.tgz
 indra/newview/pilot.txt
diff --git a/indra/cmake/BuildPackagesInfo.cmake b/indra/cmake/BuildPackagesInfo.cmake
index bc48fe5328b0f305703df3c8a3f77a3e292e54c4..348432c55d9934aadcc52a1f2488a8df1dd9d23e 100644
--- a/indra/cmake/BuildPackagesInfo.cmake
+++ b/indra/cmake/BuildPackagesInfo.cmake
@@ -17,5 +17,5 @@ add_custom_command(OUTPUT packages-info.txt
   COMMAND ${Python3_EXECUTABLE}
           ${CMAKE_SOURCE_DIR}/cmake/run_build_test.py -DAUTOBUILD_ADDRSIZE=${ADDRESS_SIZE} -DAUTOBUILD=${AUTOBUILD_EXECUTABLE}
           ${Python3_EXECUTABLE}
-          ${CMAKE_SOURCE_DIR}/../scripts/packages-formatter.py "${VIEWER_CHANNEL}" "${VIEWER_SHORT_VERSION}" "${LIBS_PREBUILT_DIR}" > packages-info.txt
+          ${CMAKE_SOURCE_DIR}/../scripts/packages-formatter.py "${VIEWER_CHANNEL}" "${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}" "${LIBS_PREBUILT_DIR}" > packages-info.txt
   )
diff --git a/indra/cmake/BuildVersion.cmake b/indra/cmake/BuildVersion.cmake
index 3f883e054031e6432aeffd206ae9b97e9bb0d208..a41718a3b8b5f983afa4b2e34637ea552431ea5c 100644
--- a/indra/cmake/BuildVersion.cmake
+++ b/indra/cmake/BuildVersion.cmake
@@ -54,20 +54,21 @@ if(NOT DEFINED VIEWER_SHORT_VERSION) # will be true in indra/, false in indra/ne
     set(VIEWER_VERSION_BASE_FILE "${CMAKE_SOURCE_DIR}/newview/VIEWER_VERSION.txt")
 
     if(EXISTS ${VIEWER_VERSION_BASE_FILE})
-        file(STRINGS ${VIEWER_VERSION_BASE_FILE} VIEWER_FILE_VERSION REGEX "^[0-9]+\\.[0-9]+")
-        string(REGEX REPLACE "^([0-9]+)\\.[0-9]+" "\\1" VIEWER_VERSION_MAJOR ${VIEWER_FILE_VERSION})
-        string(REGEX REPLACE "^[0-9]+\\.([0-9]+)" "\\1" VIEWER_VERSION_MINOR ${VIEWER_FILE_VERSION})
+        file(STRINGS ${VIEWER_VERSION_BASE_FILE} VIEWER_SHORT_VERSION REGEX "^[0-9]+\\.[0-9]+\\.[0-9]+")
+        string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+" "\\1" VIEWER_VERSION_MAJOR ${VIEWER_SHORT_VERSION})
+        string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9]+" "\\1" VIEWER_VERSION_MINOR ${VIEWER_SHORT_VERSION})
+        string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+)" "\\1" VIEWER_VERSION_PATCH ${VIEWER_SHORT_VERSION})
 
         if(REVISION_FROM_VCS)
             find_package(Git)
         endif()
 
         if((NOT REVISION_FROM_VCS) AND DEFINED ENV{CI_PIPELINE_ID})
-            set(VIEWER_VERSION_PATCH $ENV{CI_PIPELINE_ID})
-            message(STATUS "Revision (from environment): ${VIEWER_VERSION_PATCH}")
+            set(VIEWER_VERSION_REVISION $ENV{CI_PIPELINE_ID})
+            message(STATUS "Revision (from environment): ${VIEWER_VERSION_REVISION}")
         elseif((NOT REVISION_FROM_VCS) AND DEFINED ENV{AUTOBUILD_BUILD_ID})
-            set(VIEWER_VERSION_PATCH $ENV{AUTOBUILD_BUILD_ID})
-            message(STATUS "Revision (from autobuild environment): ${VIEWER_VERSION_PATCH}")
+            set(VIEWER_VERSION_REVISION $ENV{AUTOBUILD_BUILD_ID})
+            message(STATUS "Revision (from autobuild environment): ${VIEWER_VERSION_REVISION}")
         elseif(Git_FOUND)
             execute_process(
                 COMMAND ${GIT_EXECUTABLE} rev-list HEAD --count
@@ -76,26 +77,24 @@ if(NOT DEFINED VIEWER_SHORT_VERSION) # will be true in indra/, false in indra/ne
                 OUTPUT_STRIP_TRAILING_WHITESPACE)
 
             if(GIT_REV_LIST_COUNT)
-                set(VIEWER_VERSION_PATCH ${GIT_REV_LIST_COUNT})
+                set(VIEWER_VERSION_REVISION ${GIT_REV_LIST_COUNT})
             else(GIT_REV_LIST_COUNT)
-                set(VIEWER_VERSION_PATCH 0)
+                set(VIEWER_VERSION_REVISION 0)
             endif(GIT_REV_LIST_COUNT)
         else()
-            set(VIEWER_VERSION_PATCH 0)
+            set(VIEWER_VERSION_REVISION 0)
         endif()
-        message(STATUS "Building '${VIEWER_CHANNEL}' Version ${VIEWER_SHORT_VERSION}")
-
-        if("${VIEWER_VERSION_PATCH}" STREQUAL "")
-            message(STATUS "Ultimate fallback, revision was blank or not set: will use 0")
-            set(VIEWER_VERSION_PATCH 0)
-        endif("${VIEWER_VERSION_PATCH}" STREQUAL "")
-
-        set(VIEWER_SHORT_VERSION "${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}")
+        message(STATUS "Building '${VIEWER_CHANNEL}' Version ${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}")
     else(EXISTS ${VIEWER_VERSION_BASE_FILE})
         message(SEND_ERROR "Cannot get viewer version from '${VIEWER_VERSION_BASE_FILE}'")
     endif(EXISTS ${VIEWER_VERSION_BASE_FILE})
 
-    set(VIEWER_VERSION_AND_CHANNEL "${VIEWER_CHANNEL} ${VIEWER_SHORT_VERSION}")
+    if("${VIEWER_VERSION_REVISION}" STREQUAL "")
+        message(STATUS "Ultimate fallback, revision was blank or not set: will use 0")
+        set(VIEWER_VERSION_REVISION 0)
+    endif("${VIEWER_VERSION_REVISION}" STREQUAL "")
+
+    set(VIEWER_VERSION_AND_CHANNEL "${VIEWER_CHANNEL} ${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}")
 endif(NOT DEFINED VIEWER_SHORT_VERSION)
 
 if (NOT DEFINED VIEWER_COMMIT_LONG_SHA)
@@ -153,6 +152,7 @@ target_compile_definitions( ll::versioninfo INTERFACE
     LL_VIEWER_VERSION_MAJOR=${VIEWER_VERSION_MAJOR}
     LL_VIEWER_VERSION_MINOR=${VIEWER_VERSION_MINOR}
     LL_VIEWER_VERSION_PATCH=${VIEWER_VERSION_PATCH}
+    LL_VIEWER_VERSION_BUILD=${VIEWER_VERSION_REVISION}
     LL_VIEWER_COMMIT_SHA="${VIEWER_COMMIT_LONG_SHA}"
     LL_VIEWER_COMMIT_SHORT_SHA="${VIEWER_COMMIT_SHORT_SHA}"
     )
\ No newline at end of file
diff --git a/indra/llfilesystem/lldir_win32.cpp b/indra/llfilesystem/lldir_win32.cpp
index 7fa594f9163174b15be5a2d482ff1734ba59d496..afd95b1afa94da904d3cc0c4bdebe661688e461f 100644
--- a/indra/llfilesystem/lldir_win32.cpp
+++ b/indra/llfilesystem/lldir_win32.cpp
@@ -381,7 +381,7 @@ bool LLDir_Win32::fileExists(const std::string& filename) const
 
 /*virtual*/ std::string LLDir_Win32::getLLPluginLauncher()
 {
-	return gDirUtilp->getLLPluginDir() + gDirUtilp->getDirDelimiter() +
+	return gDirUtilp->getExecutableDir() + gDirUtilp->getDirDelimiter() +
 		"SLPlugin.exe";
 }
 
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 061470316c9b19f0c2f0b30e69b09ddfce8a6e94..92f667cb7814029cc03c049df87f48ecb8c24145 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -52,9 +52,6 @@ include(LLPrimitive)
 
 # Viewer Branding Assets
 use_prebuilt_binary(branding)
-if (WINDOWS)
-  use_prebuilt_binary(squirrel)
-endif()
 
 if( LLPHYSICSEXTENSIONS_SRC_DIR )
 if (NOT HAVOK_TPV)
@@ -1531,12 +1528,12 @@ source_group("CMake Rules" FILES ViewerInstall.cmake)
 #build_data.json creation moved to viewer_manifest.py MAINT-6413
 # the viewer_version.txt file created here is for passing to viewer_manifest and autobuild
 file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt"
-           "${VIEWER_SHORT_VERSION}\n")
+           "${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}\n")
 
-if (WINDOWS)
-  LIST(APPEND viewer_SOURCE_FILES alsquirrelupdater.cpp)
-  LIST(APPEND viewer_HEADER_FILES alsquirrelupdater.h)
-endif (WINDOWS)
+# if (WINDOWS)
+#  LIST(APPEND viewer_SOURCE_FILES alsquirrelupdater.cpp)
+#  LIST(APPEND viewer_HEADER_FILES alsquirrelupdater.h)
+# endif (WINDOWS)
 
 if (DARWIN)
   LIST(APPEND viewer_SOURCE_FILES llappviewermacosx.cpp)
@@ -1638,8 +1635,8 @@ if (WINDOWS)
       )
     execute_process(
       COMMAND ${CMAKE_COMMAND} -E copy_if_different
-        "${LIBS_PREBUILT_DIR}/branding/installer/splash/${ICON_PATH}/install_splash.gif"
-        "${CMAKE_CURRENT_SOURCE_DIR}/installers/windows/install_splash.gif"
+        "${LIBS_PREBUILT_DIR}/branding/installer/icons/uninstall_icon.ico"
+        "${CMAKE_CURRENT_SOURCE_DIR}/installers/windows/uninstall_icon.ico"
       )
 
     # Add resource files to the project.
@@ -1706,10 +1703,6 @@ if (WINDOWS)
                     ${CMAKE_CURRENT_BINARY_DIR}/viewerRes.rc
                     )
 
-    configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/viewer.nuspec
-                    ${CMAKE_CURRENT_BINARY_DIR}/viewer.nuspec
-                    )
-
     list(APPEND viewer_RESOURCE_FILES
     	windows.manifest
         ${CMAKE_CURRENT_BINARY_DIR}/viewerRes.rc
@@ -1760,7 +1753,6 @@ set_source_files_properties(${viewer_SHADER_FILES}
                             PROPERTIES HEADER_FILE_ONLY TRUE)
 list(APPEND viewer_SOURCE_FILES ${viewer_SHADER_FILES})
 
-
 set(viewer_APPSETTINGS_FILES
     app_settings/anim.ini
     app_settings/cmd_line.xml
@@ -1883,8 +1875,6 @@ if (WINDOWS)
         LINK_FLAGS_RELEASE "/OPT:REF /LARGEADDRESSAWARE"
         )
 
-    set_target_properties(${VIEWER_BINARY_NAME} PROPERTIES OUTPUT_NAME "${WIN_BINARY_NAME}")
-
     if(NOT LL_GENERATOR_IS_MULTI_CONFIG)
       set_target_properties(${VIEWER_BINARY_NAME} PROPERTIES
        			    RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/$<IF:$<BOOL:${LL_GENERATOR_IS_MULTI_CONFIG}>,$<CONFIG>,>")
@@ -2017,12 +2007,6 @@ if (WINDOWS)
           ${CMAKE_CURRENT_SOURCE_DIR}/event_host_manifest.py
         )
 
-      if (ENABLE_DELTA_GEN)
-        set(DELTA_GEN_SETTING "--gendelta=ON")
-      else ()
-        set(DELTA_GEN_SETTING "")
-      endif ()
-
       add_custom_command(
         OUTPUT ${CMAKE_CFG_INTDIR}/touched.bat
         COMMAND ${Python3_EXECUTABLE}
@@ -2044,7 +2028,6 @@ if (WINDOWS)
               --touch=${CMAKE_CURRENT_BINARY_DIR}/$<IF:$<BOOL:${LL_GENERATOR_IS_MULTI_CONFIG}>,$<CONFIG>,>/touched.bat
               --versionfile=${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt
               --updateurl=${VIEWER_UPDATE_SERVICE}
-              ${DELTA_GEN_SETTING}
         DEPENDS
             ${VIEWER_BINARY_NAME}
             ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
@@ -2151,7 +2134,7 @@ set(ARTWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH
     "Path to artwork files.")
 
 if (LINUX)
-  set(product Alchemy-${ARCH}-${VIEWER_SHORT_VERSION})
+  set(product Alchemy-${ARCH}-${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION})
 
   # These are the generated targets that are copied to package/
   set(COPY_INPUT_DEPENDENCIES
@@ -2232,10 +2215,10 @@ if (DARWIN)
   set(MACOSX_BUNDLE_INFO_STRING "${VIEWER_CHANNEL}")
   set(MACOSX_BUNDLE_ICON_FILE "alchemy.icns")
   set(MACOSX_BUNDLE_GUI_IDENTIFIER "org.alchemyviewer.viewer")
-  set(MACOSX_BUNDLE_LONG_VERSION_STRING "${VIEWER_CHANNEL} ${VIEWER_SHORT_VERSION}")
+  set(MACOSX_BUNDLE_LONG_VERSION_STRING "${VIEWER_CHANNEL} ${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}")
   set(MACOSX_BUNDLE_BUNDLE_NAME "Alchemy")
-  set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${VIEWER_SHORT_VERSION}")
-  set(MACOSX_BUNDLE_BUNDLE_VERSION "${VIEWER_SHORT_VERSION}")
+  set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}")
+  set(MACOSX_BUNDLE_BUNDLE_VERSION "${VIEWER_SHORT_VERSION}${VIEWER_VERSION_REVISION}")
   set(MACOSX_BUNDLE_COPYRIGHT "Copyright (C) 2013-2023 Alchemy Development Group")
   set(MACOSX_BUNDLE_NSMAIN_NIB_FILE "Alchemy.nib")
   set(MACOSX_BUNDLE_NSPRINCIPAL_CLASS "LLApplication")
@@ -2384,7 +2367,7 @@ if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIE
           "-C"
           "${PARENT_DIRECTORY_CYGWIN}"
           "alchemy-bin.pdb"
-        DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${WIN_BINARY_NAME}.pdb"
+        DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/alchemy-bin.pdb"
         COMMENT "Packing viewer PDB into ${VIEWER_SYMBOL_FILE_CYGWIN}"
         )
       add_custom_target(generate_symbols DEPENDS "${VIEWER_SYMBOL_FILE}" ${VIEWER_BINARY_NAME})
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index 4fedf1d20e15761409d6e4e3bf99c0beb499fdfe..66ce77b7ead5c03f8d614495285190635c0889d9 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-7.0
+7.0.0
diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml
index 0866b667228dc46ed04fb2991c570ddb9b830232..bcbb6a2b171f2977f1fb2a4c5f237d683d6cc30c 100644
--- a/indra/newview/app_settings/cmd_line.xml
+++ b/indra/newview/app_settings/cmd_line.xml
@@ -421,40 +421,5 @@
       <key>map-to</key>
       <string>CmdLineSkipUpdater</string>
     </map>
-    <key>squirrel-install</key>
-    <map>
-      <key>count</key>
-      <integer>1</integer>
-      <key>map-to</key>
-      <string>CmdLineSquirrelInstall</string>
-    </map>
-    <key>squirrel-firstrun</key>
-    <map>
-      <key>count</key>
-      <integer>0</integer>
-      <key>map-to</key>
-      <string>CmdLineSquirrelFirstRun</string>
-    </map>
-    <key>squirrel-updated</key>
-    <map>
-      <key>count</key>
-      <integer>1</integer>
-      <key>map-to</key>
-      <string>CmdLineSquirrelUpdated</string>
-    </map>
-    <key>squirrel-obsolete</key>
-    <map>
-      <key>count</key>
-      <integer>1</integer>
-      <key>map-to</key>
-      <string>CmdLineSquirrelObsolete</string>
-    </map>
-    <key>squirrel-uninstall</key>
-    <map>
-      <key>count</key>
-      <integer>1</integer>
-      <key>map-to</key>
-      <string>CmdLineSquirrelUninstall</string>
-    </map>
   </map>
 </llsd>
diff --git a/indra/newview/app_settings/settings_alchemy.xml b/indra/newview/app_settings/settings_alchemy.xml
index 844862144de9e625f8e8d3b10666da6ffd4e851c..1949442391a9bfc35cd7e5e5f7afa9958dc45443 100644
--- a/indra/newview/app_settings/settings_alchemy.xml
+++ b/indra/newview/app_settings/settings_alchemy.xml
@@ -827,28 +827,6 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
-    <key>AlchemyUpdatePreference</key>
-    <map>
-      <key>Comment</key>
-      <string>Default behavior of updater 0(Download and install), 1(download and prompt for install), 2(Prompt for download and install)</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>S32</string>
-      <key>Value</key>
-      <integer>0</integer>
-    </map>
-    <key>AlchemyUpdateCheckInterval</key>
-    <map>
-      <key>Comment</key>
-      <string>How frequently to check for updates in seconds.</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>F32</string>
-      <key>Value</key>
-      <real>14400.0</real>
-    </map>
     <key>ChatAlerts</key>
     <map>
       <key>Comment</key>
@@ -871,61 +849,6 @@
       <key>Value</key>
       <boolean>0</boolean>
     </map>
-    <key>CmdLineSquirrelInstall</key>
-    <map>
-      <key>Comment</key>
-      <string>Command line flag for initial install from squirrel with version as arguement</string>
-      <key>Persist</key>
-      <integer>0</integer>
-      <key>Type</key>
-      <string>String</string>
-      <key>Value</key>
-      <string />
-    </map>
-    <key>CmdLineSquirrelFirstRun</key>
-    <map>
-      <key>Comment</key>
-      <string>Command line flag for initial application run from squirrel</string>
-      <key>Persist</key>
-      <integer>0</integer>
-      <key>Type</key>
-      <string>Boolean</string>
-      <key>Value</key>
-      <integer>0</integer>
-    </map>
-    <key>CmdLineSquirrelUpdated</key>
-    <map>
-      <key>Comment</key>
-      <string>Command line flag for update from squirrel with version as arguement</string>
-      <key>Persist</key>
-      <integer>0</integer>
-      <key>Type</key>
-      <string>String</string>
-      <key>Value</key>
-      <string />
-    </map>
-    <key>CmdLineSquirrelObsolete</key>
-    <map>
-      <key>Comment</key>
-      <string>Command line flag for obsolete version from squirrel with version as arguement</string>
-      <key>Persist</key>
-      <integer>0</integer>
-      <key>Type</key>
-      <string>String</string>
-      <key>Value</key>
-      <string />
-    </map>
-    <key>CmdLineSquirrelUninstall</key>
-    <map>
-      <key>Comment</key>
-      <string>Command line flag for uninstall from squirrel with version as arguement</string>
-      <key>Persist</key>
-      <integer>0</integer>
-      <key>Type</key>
-      <string>String</string>
-      <key>Value</key>
-      <string />
-    </map>
     <key>DoubleClickAttachmentAdd</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/installers/windows/FILES_ARE_UNICODE_UTF-16LE.txt b/indra/newview/installers/windows/FILES_ARE_UNICODE_UTF-16LE.txt
new file mode 100644
index 0000000000000000000000000000000000000000..30f9349111d117a99d4af183bfb11607286239b0
--- /dev/null
+++ b/indra/newview/installers/windows/FILES_ARE_UNICODE_UTF-16LE.txt
@@ -0,0 +1,6 @@
+The language files in this directory are Unicode (Little-Endian) format, also known as UTF-16 LE.
+
+This is the format required for NSIS Unicode.  See http://www.scratchpaper.com/ for details.
+
+James Cook
+September 2008
diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi
new file mode 100644
index 0000000000000000000000000000000000000000..c782c901c37d4fb4b38fc7470f06a3467295694e
--- /dev/null
+++ b/indra/newview/installers/windows/installer_template.nsi
@@ -0,0 +1,868 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Second Life setup.nsi
+;; Copyright 2004-2015, Linden Research, Inc.
+;;
+;; This library is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU Lesser General Public
+;; License as published by the Free Software Foundation;
+;; version 2.1 of the License only.
+;;
+;; This library is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; Lesser General Public License for more details.
+;;
+;; You should have received a copy of the GNU Lesser General Public
+;; License along with this library; if not, write to the Free Software
+;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+;;
+;; Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+;;
+;; NSIS 3 or higher required for Unicode support
+;;
+;; Author: James Cook, TankMaster Finesmith, Don Kjer, Callum Prentice
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Compiler flags
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+Unicode true
+SetOverwrite on				# Overwrite files
+SetCompress auto			# Compress if saves space
+SetCompressor /solid lzma	# Compress whole installer as one block
+SetDatablockOptimize off	# Only saves us 0.1%, not worth it
+XPStyle on                  # Add an XP manifest to the installer
+RequestExecutionLevel admin	# For when we write to Program Files
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Project flags
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+# This placeholder is replaced by viewer_manifest.py
+%%VERSION%%
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; - language files - one for each language (or flavor thereof)
+;; (these files are in the same place as the nsi template but the python script generates a new nsi file in the 
+;; application directory so we have to add a path to these include files)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Ansariel notes: "Under certain circumstances the installer will fall back
+;; to the first defined (aka default) language version. So you want to include
+;; en-us as first language file."
+!include "%%SOURCE%%\installers\windows\lang_en-us.nsi"
+
+# Danish and Polish no longer supported by the viewer itself
+##!include "%%SOURCE%%\installers\windows\lang_da.nsi"
+!include "%%SOURCE%%\installers\windows\lang_de.nsi"
+!include "%%SOURCE%%\installers\windows\lang_es.nsi"
+!include "%%SOURCE%%\installers\windows\lang_fr.nsi"
+!include "%%SOURCE%%\installers\windows\lang_ja.nsi"
+!include "%%SOURCE%%\installers\windows\lang_it.nsi"
+##!include "%%SOURCE%%\installers\windows\lang_pl.nsi"
+!include "%%SOURCE%%\installers\windows\lang_pt-br.nsi"
+!include "%%SOURCE%%\installers\windows\lang_ru.nsi"
+!include "%%SOURCE%%\installers\windows\lang_tr.nsi"
+!include "%%SOURCE%%\installers\windows\lang_zh.nsi"
+
+# *TODO: Move these into the language files themselves
+##LangString LanguageCode ${LANG_DANISH}   "da"
+LangString LanguageCode ${LANG_GERMAN}   "de"
+LangString LanguageCode ${LANG_ENGLISH}  "en"
+LangString LanguageCode ${LANG_SPANISH}  "es"
+LangString LanguageCode ${LANG_FRENCH}   "fr"
+LangString LanguageCode ${LANG_JAPANESE} "ja"
+LangString LanguageCode ${LANG_ITALIAN}  "it"
+##LangString LanguageCode ${LANG_POLISH}   "pl"
+LangString LanguageCode ${LANG_PORTUGUESEBR} "pt"
+LangString LanguageCode ${LANG_RUSSIAN}  "ru"
+LangString LanguageCode ${LANG_TURKISH}  "tr"
+LangString LanguageCode ${LANG_TRADCHINESE}  "zh"
+
+# This placeholder is replaced by viewer_manifest.py
+%%INST_VARS%%
+
+Name ${INSTNAME}
+
+SubCaption 0 $(LicenseSubTitleSetup)	# Override "license agreement" text
+
+!define MUI_ICON   "%%SOURCE%%\installers\windows\install_icon.ico"
+!define MUI_UNICON "%%SOURCE%%\installers\windows\uninstall_icon.ico"
+
+BrandingText " "						# Bottom of window text
+Icon          "${MUI_ICON}"
+UninstallIcon "${MUI_UNICON}"
+WindowIcon on							# Show our icon in left corner
+BGGradient off							# No big background window
+CRCCheck on								# Make sure CRC is OK
+InstProgressFlags smooth colored		# New colored smooth look
+SetOverwrite on							# Overwrite files by default
+AutoCloseWindow true					# After all files install, close window
+
+# Registry key paths, ours and Microsoft's
+!define LINDEN_KEY      "SOFTWARE\Alchemy Development Group"
+!define INSTNAME_KEY    "${LINDEN_KEY}\${INSTNAME}"
+!define MSCURRVER_KEY   "SOFTWARE\Microsoft\Windows\CurrentVersion"
+!define MSNTCURRVER_KEY "SOFTWARE\Microsoft\Windows NT\CurrentVersion"
+!define MSUNINSTALL_KEY "${MSCURRVER_KEY}\Uninstall\${INSTNAME}"
+
+# from http://nsis.sourceforge.net/Docs/MultiUser/Readme.html
+### Highest level permitted for user: Admin for Admin, Standard for Standard
+##!define MULTIUSER_EXECUTIONLEVEL Highest
+!define MULTIUSER_EXECUTIONLEVEL Admin
+!define MULTIUSER_MUI
+### Look for /AllUsers or /CurrentUser switches
+##!define MULTIUSER_INSTALLMODE_COMMANDLINE
+# appended to $PROGRAMFILES, as affected by MULTIUSER_USE_PROGRAMFILES64
+!define MULTIUSER_INSTALLMODE_INSTDIR "${INSTNAME}"
+# expands to !define MULTIUSER_USE_PROGRAMFILES64 or nothing
+%%PROGRAMFILES%%
+# should make MultiUser.nsh initialization read existing INSTDIR from registry
+## SL-10506: don't
+##!define MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY "${INSTNAME_KEY}"
+##!define MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME ""
+# Don't set MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY and
+# MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME to cause the installer to
+# write $MultiUser.InstallMode to the registry, because when the user installs
+# multiple viewers with the same channel (same ${INSTNAME}, hence same
+# ${INSTNAME_KEY}), the registry entry is overwritten. Instead we'll write a
+# little file into the install directory -- see .onInstSuccess and un.onInit.
+!include MultiUser.nsh
+!include MUI2.nsh
+!define MUI_BGCOLOR FFFFFF
+!insertmacro MUI_FUNCTION_GUIINIT
+
+UninstallText $(UninstallTextMsg)
+DirText $(DirectoryChooseTitle) $(DirectoryChooseSetup)
+##!insertmacro MULTIUSER_PAGE_INSTALLMODE
+!define MUI_PAGE_CUSTOMFUNCTION_PRE dirPre
+!insertmacro MUI_PAGE_DIRECTORY
+!insertmacro MUI_PAGE_INSTFILES
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Variables
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+Var INSTNAME
+Var INSTEXE
+Var VIEWER_EXE
+Var INSTSHORTCUT
+Var COMMANDLINE         # Command line passed to this installer, set in .onInit
+Var SHORTCUT_LANG_PARAM # "--set InstallLanguage de", Passes language to viewer
+Var SKIP_DIALOGS        # Set from command line in  .onInit. autoinstall GUI and the defaults.
+Var SKIP_AUTORUN		# Skip automatic launch of the viewer after install
+
+# Function definitions should go before file includes, because calls to
+# DLLs like LangDLL trigger an implicit file include, so if that call is at
+# the end of this script NSIS has to decompress the whole installer before 
+# it can call the DLL function. JC
+
+!include "FileFunc.nsh"     # For GetParameters, GetOptions
+!insertmacro GetParameters
+!insertmacro GetOptions
+!include WinVer.nsh			# For OS and SP detection
+!include 'LogicLib.nsh'     # for value comparison
+!include "x64.nsh"			# for 64bit detection
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Pre-directory page callback
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+Function dirPre
+    StrCmp $SKIP_DIALOGS "true" 0 +2
+	Abort
+
+FunctionEnd    
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Prep Installer Section
+;;
+;; Note: to add new languages, add a language file include to the list 
+;; at the top of this file, add an entry to the menu and then add an 
+;; entry to the language ID selector below
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+Function .onInit
+!insertmacro MULTIUSER_INIT
+
+%%ENGAGEREGISTRY%%
+
+# SL-10506: Setting MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY and
+# MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME should
+# read the current location of the install for this version into INSTDIR.
+# However, SL-10506 complains about the resulting behavior, so the logic below
+# is adapted from before we introduced MultiUser.nsh.
+
+# if $0 is empty, this is the first time for this viewer name
+ReadRegStr $0 SHELL_CONTEXT "${INSTNAME_KEY}" ""
+
+# viewer with this name was installed before
+${If} $0 != ""
+	# use the value we got from registry as install location
+    StrCpy $INSTDIR $0
+${EndIf}
+
+Call CheckCPUFlags							# Make sure we have SSE2 support
+Call CheckWindowsVersion					# Don't install On unsupported systems
+    Push $0
+    ${GetParameters} $COMMANDLINE			# Get our command line
+
+    ${GetOptions} $COMMANDLINE "/SKIP_DIALOGS" $0   
+    IfErrors +2 0	# If error jump past setting SKIP_DIALOGS
+        StrCpy $SKIP_DIALOGS "true"
+
+	${GetOptions} $COMMANDLINE "/SKIP_AUTORUN" $0
+	IfErrors +2 0 ; If error jump past setting SKIP_AUTORUN
+		StrCpy $SKIP_AUTORUN "true"
+
+    ${GetOptions} $COMMANDLINE "/LANGID=" $0	# /LANGID=1033 implies US English
+
+# If no language (error), then proceed
+    IfErrors lbl_configure_default_lang
+# No error means we got a language, so use it
+    StrCpy $LANGUAGE $0
+    Goto lbl_return
+
+lbl_configure_default_lang:
+# If we currently have a version of SL installed, default to the language of that install
+# Otherwise don't change $LANGUAGE and it will default to the OS UI language.
+    ReadRegStr $0 SHELL_CONTEXT "${INSTNAME_KEY}" "InstallerLanguage"
+    IfErrors +2 0	# If error skip the copy instruction 
+	StrCpy $LANGUAGE $0
+
+# For silent installs, no language prompt, use default
+    IfSilent 0 +3
+    StrCpy $SKIP_AUTORUN "true"
+    Goto lbl_return
+    StrCmp $SKIP_DIALOGS "true" lbl_return
+  
+	Push ""
+# Use separate file so labels can be UTF-16 but we can still merge changes into this ASCII file. JC
+    !include "%%SOURCE%%\installers\windows\language_menu.nsi"
+    
+	Push A	# A means auto count languages for the auto count to work the first empty push (Push "") must remain
+	LangDLL::LangDialog $(InstallerLanguageTitle) $(SelectInstallerLanguage)
+	Pop $0
+	StrCmp $0 "cancel" 0 +2
+		Abort
+    StrCpy $LANGUAGE $0
+
+# Save language in registry		
+	WriteRegStr SHELL_CONTEXT "${INSTNAME_KEY}" "InstallerLanguage" $LANGUAGE
+lbl_return:
+    Pop $0
+    Return
+
+FunctionEnd
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Prep Uninstaller Section
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+Function un.onInit
+    # Save $INSTDIR -- it appears to have the correct value before
+    # MULTIUSER_UNINIT, but then gets munged by MULTIUSER_UNINIT?!
+    Push $INSTDIR
+    !insertmacro MULTIUSER_UNINIT
+    Pop $INSTDIR
+
+    # Now read InstallMode.txt from $INSTDIR
+    Push $0
+    ClearErrors
+    FileOpen $0 "$INSTDIR\InstallMode.txt" r
+    IfErrors skipread
+    FileRead $0 $MultiUser.InstallMode
+    FileClose $0
+skipread:
+    Pop $0
+
+%%ENGAGEREGISTRY%%
+
+# Read language from registry and set for uninstaller. Key will be removed on successful uninstall
+	ReadRegStr $0 SHELL_CONTEXT "${INSTNAME_KEY}" "InstallerLanguage"
+    IfErrors lbl_end
+	StrCpy $LANGUAGE $0
+lbl_end:
+
+##  MessageBox MB_OK "After restoring:$\n$$INSTDIR = '$INSTDIR'$\n$$MultiUser.InstallMode = '$MultiUser.InstallMode'$\n$$LANGUAGE = '$LANGUAGE'"
+
+    Return
+
+FunctionEnd
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Checks for CPU valid (must have SSE2 support)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+Function CheckCPUFlags
+    Push $1
+    System::Call 'kernel32::IsProcessorFeaturePresent(i) i(10) .r1'
+    IntCmp $1 1 OK_SSE2
+    MessageBox MB_OKCANCEL $(MissingSSE2) /SD IDOK IDOK OK_SSE2
+    Quit
+
+  OK_SSE2:
+    Pop $1
+    Return
+
+FunctionEnd
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Make sure this computer meets the minimum system requirements.
+;; Currently: Windows Vista SP2
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+Function CheckWindowsVersion
+  ${If} ${AtMostWin2003}
+    MessageBox MB_OK $(CheckWindowsVersionMB)
+    Quit
+  ${EndIf}
+
+  ${If} ${IsWinVista}
+  ${AndIfNot} ${IsServicePack} 2
+    MessageBox MB_OK $(CheckWindowsVersionMB)
+    Quit
+  ${EndIf}
+
+  ${If} ${IsWin2008}
+  ${AndIfNot} ${IsServicePack} 2
+    MessageBox MB_OK $(CheckWindowsVersionMB)
+    Quit
+  ${EndIf}
+
+FunctionEnd
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Install Section
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+Section ""
+
+# SetShellVarContext is set by MultiUser.nsh initialization.
+
+# Start with some default values.
+StrCpy $INSTNAME "${INSTNAME}"
+StrCpy $INSTEXE "${INSTEXE}"
+StrCpy $VIEWER_EXE "${VIEWER_EXE}"
+StrCpy $INSTSHORTCUT "${SHORTCUT}"
+
+Call CheckIfAdministrator		# Make sure the user can install/uninstall
+Call CloseSecondLife			# Make sure Second Life not currently running
+
+ClearErrors
+
+INSTALL_FILES_START:
+
+Call RemoveProgFilesOnInst		# Remove existing files to prevent certain errors when running the new version of the viewer
+
+# This placeholder is replaced by the complete list of all the files in the installer, by viewer_manifest.py
+%%INSTALL_FILES%%
+
+IfErrors 0 INSTALL_FILES_DONE
+  StrCmp $SKIP_DIALOGS "true" INSTALL_FILES_DONE
+	MessageBox MB_ABORTRETRYIGNORE $(ErrorSecondLifeInstallRetry) IDABORT INSTALL_FILES_CANCEL IDRETRY INSTALL_FILES_START
+    # MB_ABORTRETRYIGNORE does not accept IDIGNORE
+    Goto INSTALL_FILES_DONE
+
+INSTALL_FILES_CANCEL:
+  # We are quiting, cleanup.
+  # Silence warnings from RemoveProgFilesOnInst.
+  StrCpy $SKIP_DIALOGS "true"
+  Call RemoveProgFilesOnInst
+  MessageBox MB_OK $(ErrorSecondLifeInstallSupport)
+  Quit
+
+INSTALL_FILES_DONE:
+
+# Pass the installer's language to the client to use as a default
+StrCpy $SHORTCUT_LANG_PARAM "--set InstallLanguage $(LanguageCode)"
+
+# Shortcuts in start menu
+CreateDirectory	"$SMPROGRAMS\$INSTSHORTCUT"
+SetOutPath "$INSTDIR"
+CreateShortCut	"$SMPROGRAMS\$INSTSHORTCUT\$INSTSHORTCUT.lnk" \
+				"$INSTDIR\$VIEWER_EXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE"
+
+
+WriteINIStr		"$SMPROGRAMS\$INSTSHORTCUT\SL Create Account.url" \
+				"InternetShortcut" "URL" \
+				"http://join.secondlife.com/"
+WriteINIStr		"$SMPROGRAMS\$INSTSHORTCUT\SL Your Account.url" \
+				"InternetShortcut" "URL" \
+				"http://www.secondlife.com/account/"
+WriteINIStr		"$SMPROGRAMS\$INSTSHORTCUT\SL Scripting Language Help.url" \
+				"InternetShortcut" "URL" \
+                "http://wiki.secondlife.com/wiki/LSL_Portal"
+CreateShortCut	"$SMPROGRAMS\$INSTSHORTCUT\Uninstall $INSTSHORTCUT.lnk" \
+				'"$INSTDIR\uninst.exe"' ''
+
+# Other shortcuts
+SetOutPath "$INSTDIR"
+CreateShortCut "$DESKTOP\$INSTSHORTCUT.lnk" \
+        "$INSTDIR\$VIEWER_EXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE"
+CreateShortCut "$INSTDIR\$INSTSHORTCUT.lnk" \
+        "$INSTDIR\$VIEWER_EXE" "$SHORTCUT_LANG_PARAM" "$INSTDIR\$VIEWER_EXE"
+CreateShortCut "$INSTDIR\Uninstall $INSTSHORTCUT.lnk" \
+				'"$INSTDIR\uninst.exe"' ''
+
+# Write registry
+WriteRegStr SHELL_CONTEXT "${INSTNAME_KEY}" "" "$INSTDIR"
+WriteRegStr SHELL_CONTEXT "${INSTNAME_KEY}" "Version" "${VERSION_LONG}"
+WriteRegStr SHELL_CONTEXT "${INSTNAME_KEY}" "Shortcut" "$INSTSHORTCUT"
+WriteRegStr SHELL_CONTEXT "${INSTNAME_KEY}" "Exe" "$VIEWER_EXE"
+WriteRegStr SHELL_CONTEXT "${MSUNINSTALL_KEY}" "Publisher" "Alchemy Development Group"
+WriteRegStr SHELL_CONTEXT "${MSUNINSTALL_KEY}" "URLInfoAbout" "https://alchemyviewer.org/pages/about.html"
+WriteRegStr SHELL_CONTEXT "${MSUNINSTALL_KEY}" "URLUpdateInfo" "https://alchemyviewer.org/pages/downloads.html"
+WriteRegStr SHELL_CONTEXT "${MSUNINSTALL_KEY}" "HelpLink" "https://alchemyviewer.org/"
+WriteRegStr SHELL_CONTEXT "${MSUNINSTALL_KEY}" "DisplayName" "$INSTNAME"
+WriteRegStr SHELL_CONTEXT "${MSUNINSTALL_KEY}" "UninstallString" '"$INSTDIR\uninst.exe"'
+WriteRegStr SHELL_CONTEXT "${MSUNINSTALL_KEY}" "DisplayVersion" "${VERSION_LONG}"
+WriteRegDWORD SHELL_CONTEXT "${MSUNINSTALL_KEY}" "EstimatedSize" "0x0001D500"		# ~117 MB
+
+# from FS:Ansariel
+WriteRegStr SHELL_CONTEXT "${MSUNINSTALL_KEY}" "DisplayIcon" '"$INSTDIR\$VIEWER_EXE"'
+
+# Write URL registry info
+WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}" "(default)" "URL:Second Life"
+WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}" "URL Protocol" ""
+WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}\DefaultIcon" "" '"$INSTDIR\$VIEWER_EXE"'
+
+# URL param must be last item passed to viewer, it ignores subsequent params to avoid parameter injection attacks.
+# MAINT-8305: On SLURL click, directly invoke the viewer, not the launcher.
+WriteRegExpandStr HKEY_CLASSES_ROOT "${URLNAME}\shell\open\command" "" '"$INSTDIR\$VIEWER_EXE" -url "%1"'
+
+WriteRegStr HKEY_CLASSES_ROOT "x-grid-info" "(default)" "URL:Hypergrid"
+WriteRegStr HKEY_CLASSES_ROOT "x-grid-info" "URL Protocol" ""
+WriteRegStr HKEY_CLASSES_ROOT "x-grid-info\DefaultIcon" "" '"$INSTDIR\$VIEWER_EXE"'
+
+# URL param must be last item passed to viewer, it ignores subsequent params to avoid parameter injection attacks.
+WriteRegExpandStr HKEY_CLASSES_ROOT "x-grid-location-info\shell\open\command" "" '"$INSTDIR\$VIEWER_EXE" -url "%1"'
+
+WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info" "(default)" "URL:Hypergrid"
+WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info" "URL Protocol" ""
+WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info\DefaultIcon" "" '"$INSTDIR\$VIEWER_EXE"'
+
+# URL param must be last item passed to viewer, it ignores subsequent params to avoid parameter injection attacks.
+WriteRegExpandStr HKEY_CLASSES_ROOT "x-grid-location-info\shell\open\command" "" '"$INSTDIR\$VIEWER_EXE" -url "%1"'
+
+WriteRegStr HKEY_CLASSES_ROOT "Applications\$INSTEXE" "IsHostApp" ""
+##WriteRegStr HKEY_CLASSES_ROOT "Applications\${VIEWER_EXE}" "NoStartPage" ""
+
+# Write out uninstaller
+WriteUninstaller "$INSTDIR\uninst.exe"
+
+SectionEnd
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Uninstall Section
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+Section Uninstall
+
+# Start with some default values.
+StrCpy $INSTNAME "${INSTNAME}"
+StrCpy $INSTEXE "${INSTEXE}"
+StrCpy $VIEWER_EXE "${VIEWER_EXE}"
+StrCpy $INSTSHORTCUT "${SHORTCUT}"
+
+# SetShellVarContext per the mode saved at install time in registry at
+# MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY
+# MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME
+# Couldn't get NSIS to expand $MultiUser.InstallMode into the function name at Call time
+${If} $MultiUser.InstallMode == 'AllUsers'
+##MessageBox MB_OK "Uninstalling for all users"
+  Call un.MultiUser.InstallMode.AllUsers
+${Else}
+##MessageBox MB_OK "Uninstalling for current user"
+  Call un.MultiUser.InstallMode.CurrentUser
+${EndIf}
+
+# Make sure we're not running
+Call un.CloseSecondLife
+
+# Clean up registry keys and subkeys (these should all be !defines somewhere)
+DeleteRegKey SHELL_CONTEXT "${INSTNAME_KEY}"
+DeleteRegKey SHELL_CONTEXT "${MSCURRVER_KEY}\Uninstall\$INSTNAME"
+# BUG-2707 Remove entry that disabled SEHOP
+DeleteRegKey SHELL_CONTEXT "${MSNTCURRVER_KEY}\Image File Execution Options\$VIEWER_EXE"
+DeleteRegKey HKEY_CLASSES_ROOT "Applications\$INSTEXE"
+DeleteRegKey HKEY_CLASSES_ROOT "Applications\${VIEWER_EXE}"
+
+# Clean up shortcuts
+Delete "$SMPROGRAMS\$INSTSHORTCUT\*.*"
+RMDir  "$SMPROGRAMS\$INSTSHORTCUT"
+
+Delete "$DESKTOP\$INSTSHORTCUT.lnk"
+Delete "$INSTDIR\$INSTSHORTCUT.lnk"
+Delete "$INSTDIR\Uninstall $INSTSHORTCUT.lnk"
+
+# Remove the main installation directory
+Call un.ProgramFiles
+
+# Clean up cache and log files, but leave them in-place for non AGNI installs.
+Call un.UserSettingsFiles
+
+SectionEnd
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Make sure the user can install
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+Function CheckIfAdministrator
+    DetailPrint $(CheckAdministratorInstDP)
+    UserInfo::GetAccountType
+    Pop $R0
+    StrCmp $R0 "Admin" lbl_is_admin
+        MessageBox MB_OK $(CheckAdministratorInstMB)
+        Quit
+lbl_is_admin:
+    Return
+
+FunctionEnd
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Close the program, if running. Modifies no variables.
+;; Allows user to bail out of install process.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+Function CloseSecondLife
+  Push $0
+  FindWindow $0 "Alchemy" ""
+  IntCmp $0 0 DONE
+  
+  StrCmp $SKIP_DIALOGS "true" CLOSE
+    MessageBox MB_OKCANCEL $(CloseSecondLifeInstMB) IDOK CLOSE IDCANCEL CANCEL_INSTALL
+
+  CANCEL_INSTALL:
+    Quit
+
+  CLOSE:
+    DetailPrint $(CloseSecondLifeInstDP)
+    SendMessage $0 16 0 0
+
+  LOOP:
+	  FindWindow $0 "Alchemy" ""
+	  IntCmp $0 0 SLEEP
+	  Sleep 500
+	  Goto LOOP
+	  
+  SLEEP:
+    # Second life window just closed, but program might not be fully done yet
+    # and OS might have not released some locks, wait a bit more to make sure
+    # all file handles were released.
+	# If something still isn't unlocked, it will trigger a notification from
+	# RemoveProgFilesOnInst
+    Sleep 1000
+  DONE:
+    Pop $0
+    Return
+
+FunctionEnd
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Close the program, if running. Modifies no variables.
+;; Allows user to bail out of uninstall process.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+Function un.CloseSecondLife
+  Push $0
+  FindWindow $0 "Alchemy" ""
+  IntCmp $0 0 DONE
+  MessageBox MB_OKCANCEL $(CloseSecondLifeUnInstMB) IDOK CLOSE IDCANCEL CANCEL_UNINSTALL
+
+  CANCEL_UNINSTALL:
+    Quit
+
+  CLOSE:
+    DetailPrint $(CloseSecondLifeUnInstDP)
+    SendMessage $0 16 0 0
+
+  LOOP:
+	  FindWindow $0 "Alchemy" ""
+	  IntCmp $0 0 DONE
+	  Sleep 500
+	  Goto LOOP
+
+  DONE:
+    Pop $0
+    Return
+
+FunctionEnd
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Delete files on install if previous install exists to prevent undesired behavior
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+Function RemoveProgFilesOnInst
+
+# We do not remove whole pervious install folder on install, since
+# there is a chance that viewer was installed into some important
+# folder by intent or accident
+# RMDir /r $INSTDIR is especially unsafe if user installed somewhere
+# like Program Files
+
+# Set retry counter. All integers are strings.
+Push $0
+StrCpy $0 0
+
+ClearErrors
+
+PREINSTALL_REMOVE:
+
+# Remove old SecondLife.exe to invalidate any old shortcuts to it that may be in non-standard locations. See MAINT-3575
+Delete "$INSTDIR\$INSTEXE"
+Delete "$INSTDIR\$VIEWER_EXE"
+
+# Remove old shader files first so fallbacks will work. See DEV-5663
+RMDir /r "$INSTDIR\app_settings\shaders"
+
+# Remove folders to clean up files removed during development
+RMDir /r "$INSTDIR\app_settings"
+RMDir /r "$INSTDIR\skins"
+RMDir /r "$INSTDIR\vmp_icons"
+
+# Remove llplugin, plugins can crash or malfunction if they
+# find modules from different versions
+RMDir /r "$INSTDIR\llplugin"
+
+IntOp $0 $0 + 1
+
+IfErrors 0 PREINSTALL_DONE
+  IntCmp $0 1 PREINSTALL_REMOVE #try again once
+    StrCmp $SKIP_DIALOGS "true" PREINSTALL_DONE
+      MessageBox MB_ABORTRETRYIGNORE $(CloseSecondLifeInstRM) IDABORT PREINSTALL_FAIL IDRETRY PREINSTALL_REMOVE
+      # MB_ABORTRETRYIGNORE does not accept IDIGNORE
+      Goto PREINSTALL_DONE
+
+PREINSTALL_FAIL:
+    Quit
+
+PREINSTALL_DONE:
+
+# We are no longer including release notes with the viewer, so remove them.
+Delete "$SMPROGRAMS\$INSTSHORTCUT\SL Release Notes.lnk"
+Delete "$INSTDIR\releasenotes.txt"
+
+Pop $0
+
+FunctionEnd
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Delete files in \Users\<User>\AppData\
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+Function un.UserSettingsFiles
+
+# Ask if user wants to keep data files or not
+MessageBox MB_YESNO|MB_ICONQUESTION $(RemoveDataFilesMB) IDYES Remove IDNO Keep
+
+Remove:
+Push $0
+Push $1
+Push $2
+
+  DetailPrint "Deleting Alchemy data files"
+
+  StrCpy $0 0	# Index number used to iterate via EnumRegKey
+
+  LOOP:
+    EnumRegKey $1 SHELL_CONTEXT "${MSNTCURRVER_KEY}\ProfileList" $0
+    StrCmp $1 "" DONE               # No more users
+
+    ReadRegStr $2 SHELL_CONTEXT "${MSNTCURRVER_KEY}\ProfileList\$1" "ProfileImagePath" 
+    StrCmp $2 "" CONTINUE 0         # "ProfileImagePath" value is missing
+
+# Required since ProfileImagePath is of type REG_EXPAND_SZ
+    ExpandEnvStrings $2 $2
+
+# Delete files in \Users\<User>\AppData\Roaming\AlchemyNext
+# Remove all settings files but leave any other .txt files to preserve the chat logs
+;    RMDir /r "$2\AppData\Roaming\AlchemyNext\logs"
+    RMDir /r "$2\AppData\Roaming\AlchemyNext\browser_profile"
+    RMDir /r "$2\AppData\Roaming\AlchemyNext\user_settings"
+    Delete  "$2\AppData\Roaming\AlchemyNext\*.xml"
+    Delete  "$2\AppData\Roaming\AlchemyNext\*.bmp"
+    Delete  "$2\AppData\Roaming\AlchemyNext\search_history.txt"
+    Delete  "$2\AppData\Roaming\AlchemyNext\plugin_cookies.txt"
+    Delete  "$2\AppData\Roaming\AlchemyNext\typed_locations.txt"
+# Delete files in \Users\<User>\AppData\Local\AlchemyNext
+    RmDir /r  "$2\AppData\Local\AlchemyNext"							#Delete the cache folder
+
+  CONTINUE:
+    IntOp $0 $0 + 1
+    Goto LOOP
+  DONE:
+
+Pop $2
+Pop $1
+Pop $0
+
+# Delete files in ProgramData\Secondlife
+Push $0
+  ReadRegStr $0 SHELL_CONTEXT "${MSCURRVER_KEY}\Explorer\Shell Folders" "Common AppData"
+  StrCmp $0 "" +2
+  RMDir /r "$0\Alchemy"
+Pop $0
+
+Keep:
+
+FunctionEnd
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Delete the installed files
+;; This deletes the uninstall executable, but it works because it is copied to temp directory before running
+;;
+;; Note:  You must list all files here, because we only want to delete our files,
+;; not things users left in the program directory.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+Function un.ProgramFiles
+
+# This placeholder is replaced by the complete list of files to uninstall by viewer_manifest.py
+%%DELETE_FILES%%
+
+# our InstallMode.txt
+Delete "$INSTDIR\InstallMode.txt"
+
+# Optional/obsolete files.  Delete won't fail if they don't exist.
+Delete "$INSTDIR\autorun.bat"
+Delete "$INSTDIR\dronesettings.ini"
+Delete "$INSTDIR\message_template.msg"
+Delete "$INSTDIR\newview.pdb"
+Delete "$INSTDIR\newview.map"
+Delete "$INSTDIR\Alchemy.pdb"
+Delete "$INSTDIR\Alchemy.map"
+Delete "$INSTDIR\comm.dat"
+Delete "$INSTDIR\*.glsl"
+Delete "$INSTDIR\motions\*.lla"
+Delete "$INSTDIR\trial\*.html"
+Delete "$INSTDIR\newview.exe"
+Delete "$INSTDIR\Alchemy.exe"
+
+# MAINT-3099 workaround - prevent these log files, if present, from causing a user alert
+Delete "$INSTDIR\VivoxVoiceService-*.log"
+
+# Remove entire help directory
+RMDir /r  "$INSTDIR\help"
+
+Delete "$INSTDIR\uninst.exe"
+RMDir "$INSTDIR"
+
+IfFileExists "$INSTDIR" FOLDERFOUND NOFOLDER
+
+FOLDERFOUND:
+  MessageBox MB_OK $(DeleteProgramFilesMB) /SD IDOK IDOK NOFOLDER
+
+NOFOLDER:
+
+MessageBox MB_YESNO $(DeleteRegistryKeysMB) IDYES DeleteKeys IDNO NoDelete
+
+DeleteKeys:
+  DeleteRegKey SHELL_CONTEXT "SOFTWARE\Classes\x-grid-location-info"
+  DeleteRegKey SHELL_CONTEXT "SOFTWARE\Classes\secondlife"
+  DeleteRegKey HKEY_CLASSES_ROOT "x-grid-location-info"
+  DeleteRegKey HKEY_CLASSES_ROOT "x-grid-info"
+  DeleteRegKey HKEY_CLASSES_ROOT "secondlife"
+
+NoDelete:
+
+FunctionEnd
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; After install completes, launch app
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+Function .onInstSuccess
+        Push $0
+        FileOpen $0 "$INSTDIR\InstallMode.txt" w
+        # No newline -- this is for our use, not for users to read.
+        FileWrite $0 "$MultiUser.InstallMode"
+        FileClose $0
+        Pop $0
+
+        Push $R0
+        Push $0
+        ;; MAINT-7812: Only write nsis.winstall file with /marker switch
+        ${GetParameters} $R0
+        ${GetOptionsS} $R0 "/marker" $0
+        ;; If no /marker switch, skip to ClearErrors
+        IfErrors +4 0
+        ;; $EXEDIR is where we find the installer file
+        ;; Put a marker file there so VMP will know we're done
+        ;; and it can delete the download directory next time.
+        ;; http://nsis.sourceforge.net/Write_text_to_a_file
+        FileOpen $0 "$EXEDIR\nsis.winstall" w
+        FileWrite $0 "NSIS done$\n"
+        FileClose $0
+
+        ClearErrors
+        Pop $0
+        Pop $R0
+
+        Call CheckWindowsServPack		# Warn if not on the latest SP before asking to launch.
+        StrCmp $SKIP_AUTORUN "true" +2;
+        # Assumes SetOutPath $INSTDIR
+        # Run INSTEXE (our updater), passing VIEWER_EXE plus the command-line
+        # arguments built into our shortcuts. This gives the updater a chance
+        # to verify that the viewer we just installed is appropriate for the
+        # running system -- or, if not, to download and install a different
+        # viewer. For instance, if a user running 32-bit Windows installs a
+        # 64-bit viewer, it cannot run on this system. But since the updater
+        # is a 32-bit executable even in the 64-bit viewer package, the
+        # updater can detect the problem and adapt accordingly.
+        # Once everything is in order, the updater will run the specified
+        # viewer with the specified params.
+        # Quote the updater executable and the viewer executable because each
+        # must be a distinct command-line token, but DO NOT quote the language
+        # string because it must decompose into separate command-line tokens.
+        Exec '"$INSTDIR\$INSTEXE" precheck "$INSTDIR\$VIEWER_EXE" $SHORTCUT_LANG_PARAM'
+# 
+FunctionEnd
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Recommend Upgrading to Service Pack 1 for Windows 7, if not present
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+Function CheckWindowsServPack
+  ${If} ${IsWin7}
+  ${AndIfNot} ${IsServicePack} 1
+    MessageBox MB_OK $(CheckWindowsServPackMB)
+    DetailPrint $(UseLatestServPackDP)
+    Return
+  ${EndIf}
+
+  ${If} ${IsWin2008R2}
+  ${AndIfNot} ${IsServicePack} 1
+    MessageBox MB_OK $(CheckWindowsServPackMB)
+    DetailPrint $(UseLatestServPackDP)
+    Return
+  ${EndIf}
+
+FunctionEnd
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Clobber user files - TEST ONLY
+;; This is here for testing, DO NOT USE UNLESS YOU KNOW WHAT YOU ARE TESTING FOR!
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;Function ClobberUserFilesTESTONLY
+
+;Push $0
+;Push $1
+;Push $2
+;
+;    StrCpy $0 0	# Index number used to iterate via EnumRegKey
+;
+;  LOOP:
+;    EnumRegKey $1 SHELL_CONTEXT "${MSNTCURRVER_KEY}\ProfileList" $0
+;    StrCmp $1 "" DONE               # no more users
+;
+;    ReadRegStr $2 SHELL_CONTEXT "${MSNTCURRVER_KEY}\ProfileList\$1" "ProfileImagePath"
+;    StrCmp $2 "" CONTINUE 0         # "ProfileImagePath" value is missing
+;
+;# Required since ProfileImagePath is of type REG_EXPAND_SZ
+;    ExpandEnvStrings $2 $2
+;
+;    RMDir /r "$2\Application Data\SecondLife\"
+;
+;  CONTINUE:
+;    IntOp $0 $0 + 1
+;    Goto LOOP
+;  DONE:
+;
+;Pop $2
+;Pop $1
+;Pop $0
+;
+;# Copy files in Documents and Settings\All Users\SecondLife
+;Push $0
+;    ReadRegStr $0 SHELL_CONTEXT "${MSCURRVER_KEY}\Explorer\Shell Folders" "Common AppData"
+;    StrCmp $0 "" +2
+;    RMDir /r "$2\Application Data\SecondLife\"
+;Pop $0
+;
+;FunctionEnd
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; EOF  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/indra/newview/installers/windows/lang_da.nsi b/indra/newview/installers/windows/lang_da.nsi
new file mode 100644
index 0000000000000000000000000000000000000000..73f23086be22efa016f61757a0246ad56a929a6c
Binary files /dev/null and b/indra/newview/installers/windows/lang_da.nsi differ
diff --git a/indra/newview/installers/windows/lang_de.nsi b/indra/newview/installers/windows/lang_de.nsi
new file mode 100644
index 0000000000000000000000000000000000000000..f67a09f84c6f81d44099fcfab04729e8af9e0850
--- /dev/null
+++ b/indra/newview/installers/windows/lang_de.nsi
@@ -0,0 +1,90 @@
+; First is default
+LoadLanguageFile "${NSISDIR}\Contrib\Language files\German.nlf"
+
+; Language selection dialog
+LangString InstallerLanguageTitle  ${LANG_GERMAN} "Installationssprache"
+LangString SelectInstallerLanguage  ${LANG_GERMAN} "Bitte wählen Sie die Installationssprache"
+
+; subtitle on license text caption (setup new version or update current one
+LangString LicenseSubTitleUpdate ${LANG_GERMAN} " Update"
+LangString LicenseSubTitleSetup ${LANG_GERMAN} " Setup"
+
+LangString MULTIUSER_TEXT_INSTALLMODE_TITLE ${LANG_GERMAN} "Installationsmodus"
+LangString MULTIUSER_TEXT_INSTALLMODE_SUBTITLE ${LANG_GERMAN} "Für alle Benutzer (erfordert Administratorrechte) oder nur für den aktuellen Benutzer installieren?"
+LangString MULTIUSER_INNERTEXT_INSTALLMODE_TOP ${LANG_GERMAN} "Wenn Sie dieses Installationsprogram mit Administratorrechten ausführen, können Sie auswählen, ob die Installation (beispielsweise) in c:\Programme oder unter AppData\Lokaler Ordner des aktuellen Benutzers erfolgen soll."
+LangString MULTIUSER_INNERTEXT_INSTALLMODE_ALLUSERS ${LANG_GERMAN} "Für alle Benutzer installieren"
+LangString MULTIUSER_INNERTEXT_INSTALLMODE_CURRENTUSER ${LANG_GERMAN} "Nur für den aktuellen Benutzer installieren"
+
+; installation directory text
+LangString DirectoryChooseTitle ${LANG_GERMAN} "Installations-Ordner"
+LangString DirectoryChooseUpdate ${LANG_GERMAN} "Wählen Sie den Second Life Ordner für dieses Update:"
+LangString DirectoryChooseSetup ${LANG_GERMAN} "Pfad in dem Second Life installiert werden soll:"
+
+LangString MUI_TEXT_DIRECTORY_TITLE ${LANG_GERMAN} "Installationsverzeichnis"
+LangString MUI_TEXT_DIRECTORY_SUBTITLE ${LANG_GERMAN} "Wählen Sie das Verzeichnis aus, in dem Second Life installiert werden soll:"
+
+LangString MUI_TEXT_INSTALLING_TITLE ${LANG_GERMAN} "Second Life wird installiert..."
+LangString MUI_TEXT_INSTALLING_SUBTITLE ${LANG_GERMAN} "Der Second Life Viewer wird im Verzeichnis $INSTDIR installiert"
+
+LangString MUI_TEXT_FINISH_TITLE ${LANG_GERMAN} "Second Life wird installiert"
+LangString MUI_TEXT_FINISH_SUBTITLE ${LANG_GERMAN} "Der Second Life Viewer wurde im Verzeichnis $INSTDIR installiert."
+
+LangString MUI_TEXT_ABORT_TITLE ${LANG_GERMAN} "Installation abgebrochen"
+LangString MUI_TEXT_ABORT_SUBTITLE ${LANG_GERMAN} "Der Second Life Viewer wird nicht im Verzeichnis $INSTDIR installiert."
+
+; CheckStartupParams message box
+LangString CheckStartupParamsMB ${LANG_GERMAN} "Konnte Programm '$INSTNAME' nicht finden. Stilles Update fehlgeschlagen."
+
+; installation success dialog
+LangString InstSuccesssQuestion ${LANG_GERMAN} "Second Life starten?"
+
+; remove old NSIS version
+LangString RemoveOldNSISVersion ${LANG_GERMAN} "Überprüfe alte Version ..."
+
+; check windows version
+LangString CheckWindowsVersionDP ${LANG_GERMAN} "Überprüfung der Windows Version ..."
+LangString CheckWindowsVersionMB ${LANG_GERMAN} 'Second Life unterstützt nur Windows Vista.$\n$\nDer Versuch es auf Windows $R0 zu installieren, könnte zu unvorhersehbaren Abstürzen und Datenverlust führen.$\n$\nTrotzdem installieren?'
+LangString CheckWindowsServPackMB ${LANG_GERMAN} "Wir empfehlen, das neueste Service Pack für Ihr Betriebssystem zu installieren, um Second Life auszuführen.$\nDies unterstützt die Leistung und Stabilität des Programms."
+LangString UseLatestServPackDP ${LANG_GERMAN} "Bitte verwenden Sie Windows Update, um das neueste Service Pack zu installieren."
+
+; checkifadministrator function (install)
+LangString CheckAdministratorInstDP ${LANG_GERMAN} "Überprüfung der Installations-Berechtigungen ..."
+LangString CheckAdministratorInstMB ${LANG_GERMAN} 'Sie besitzen ungenügende Berechtigungen.$\nSie müssen ein "administrator" sein, um Second Life installieren zu können.'
+
+; checkifadministrator function (uninstall)
+LangString CheckAdministratorUnInstDP ${LANG_GERMAN} "Überprüfung der Entfernungs-Berechtigungen ..."
+LangString CheckAdministratorUnInstMB ${LANG_GERMAN} 'Sie besitzen ungenügende Berechtigungen.$\nSie müssen ein "administrator" sein, um Second Life entfernen zu können..'
+
+; checkifalreadycurrent
+LangString CheckIfCurrentMB ${LANG_GERMAN} "Anscheinend ist Second Life ${VERSION_LONG} bereits installiert.$\n$\nWürden Sie es gerne erneut installieren?"
+
+; checkcpuflags
+LangString MissingSSE2 ${LANG_GERMAN} "Dieses Gerät verfügt möglicherweise nicht über eine CPU mit SSE2-Unterstützung, die für Second Life ${VERSION_LONG} benötigt wird. Möchten Sie fortfahren?"
+
+; closesecondlife function (install)
+LangString CloseSecondLifeInstDP ${LANG_GERMAN} "Warten auf die Beendigung von Second Life ..."
+LangString CloseSecondLifeInstMB ${LANG_GERMAN} "Second Life kann nicht installiert oder ersetzt werden, wenn es bereits läuft.$\n$\nBeenden Sie, was Sie gerade tun und klicken Sie OK, um Second Life zu beenden.$\nKlicken Sie CANCEL, um die Installation abzubrechen."
+LangString CloseSecondLifeInstRM ${LANG_GERMAN} "Second Life failed to remove some files from a previous install."
+
+; closesecondlife function (uninstall)
+LangString CloseSecondLifeUnInstDP ${LANG_GERMAN} "Warten auf die Beendigung von Second Life ..."
+LangString CloseSecondLifeUnInstMB ${LANG_GERMAN} "Second Life kann nicht entfernt werden, wenn es bereits läuft.$\n$\nBeenden Sie, was Sie gerade tun und klicken Sie OK, um Second Life zu beenden.$\nKlicken Sie CANCEL, um abzubrechen."
+
+; CheckNetworkConnection
+LangString CheckNetworkConnectionDP ${LANG_GERMAN} "Prüfe Netzwerkverbindung..."
+
+; error during installation
+LangString ErrorSecondLifeInstallRetry ${LANG_GERMAN} "Second Life konnte nicht korrekt installiert werden, einige Dateien wurden eventuell nicht korrekt von der Installationroutine kopiert."
+LangString ErrorSecondLifeInstallSupport ${LANG_GERMAN} "Bitte laden Sie den Viewer erneut von https://secondlife.com/support/downloads/ und versuchen Sie die Installation erneut. Sollte das Problem weiterhin bestehen, dann kontaktieren Sie unseren Support unter https://support.secondlife.com."
+
+; ask to remove user's data files
+LangString RemoveDataFilesMB ${LANG_GERMAN} "Möchten Sie alle anderen zu Second Life gehörigen Dateien ebenfalls ENTFERNEN?$\n$\nWir empfehlen, die Einstellungen und Cache-Dateien zu behalten, wenn Sie andere Versionen von Second Life installiert haben oder eine Deinstallation durchführen, um Second Life auf eine neuere Version zu aktualisieren."
+
+; delete program files
+LangString DeleteProgramFilesMB ${LANG_GERMAN} "Es existieren weiterhin Dateien in Ihrem SecondLife Programm Ordner.$\n$\nDies sind möglicherweise Dateien, die sie modifiziert oder bewegt haben:$\n$INSTDIR$\n$\nMöchten Sie diese ebenfalls löschen?"
+
+; uninstall text
+LangString UninstallTextMsg ${LANG_GERMAN} "Dies wird Second Life ${VERSION_LONG} von Ihrem System entfernen."
+
+; ask to remove registry keys that still might be needed by other viewers that are installed
+LangString DeleteRegistryKeysMB ${LANG_GERMAN} "Möchten Sie die Registrierungsschlüssel der Anwendung entfernen?$\n$\nWir empfehlen, die Registrierungsschlüssel zu behalten, wenn Sie andere Versionen von Second Life installiert haben."
diff --git a/indra/newview/installers/windows/lang_en-us.nsi b/indra/newview/installers/windows/lang_en-us.nsi
new file mode 100644
index 0000000000000000000000000000000000000000..9d00f1b4c0c2389604174f9343cf20fccea9288f
Binary files /dev/null and b/indra/newview/installers/windows/lang_en-us.nsi differ
diff --git a/indra/newview/installers/windows/lang_es.nsi b/indra/newview/installers/windows/lang_es.nsi
new file mode 100644
index 0000000000000000000000000000000000000000..364cc9f67e2f9aa7b05498d848d38b56ab22e429
Binary files /dev/null and b/indra/newview/installers/windows/lang_es.nsi differ
diff --git a/indra/newview/installers/windows/lang_fr.nsi b/indra/newview/installers/windows/lang_fr.nsi
new file mode 100644
index 0000000000000000000000000000000000000000..2f34c0c87a1552dd0632baf63dd53cc9bf1edf7b
Binary files /dev/null and b/indra/newview/installers/windows/lang_fr.nsi differ
diff --git a/indra/newview/installers/windows/lang_it.nsi b/indra/newview/installers/windows/lang_it.nsi
new file mode 100644
index 0000000000000000000000000000000000000000..51214d3a9ce88d5a594a6ab02ea3b8f4b09af8e2
Binary files /dev/null and b/indra/newview/installers/windows/lang_it.nsi differ
diff --git a/indra/newview/installers/windows/lang_ja.nsi b/indra/newview/installers/windows/lang_ja.nsi
new file mode 100644
index 0000000000000000000000000000000000000000..296703d1a3e94080fe18709d1e5ac3031887cde7
Binary files /dev/null and b/indra/newview/installers/windows/lang_ja.nsi differ
diff --git a/indra/newview/installers/windows/lang_pl.nsi b/indra/newview/installers/windows/lang_pl.nsi
new file mode 100644
index 0000000000000000000000000000000000000000..299645bbb78010298d43366cfa5dd3299081a096
Binary files /dev/null and b/indra/newview/installers/windows/lang_pl.nsi differ
diff --git a/indra/newview/installers/windows/lang_pt-br.nsi b/indra/newview/installers/windows/lang_pt-br.nsi
new file mode 100644
index 0000000000000000000000000000000000000000..542c8654b5bffbe4d6f57a90c878c329ce7eb997
Binary files /dev/null and b/indra/newview/installers/windows/lang_pt-br.nsi differ
diff --git a/indra/newview/installers/windows/lang_ru.nsi b/indra/newview/installers/windows/lang_ru.nsi
new file mode 100644
index 0000000000000000000000000000000000000000..4e53a4957d49d2cf9b11df0b1ac0849a3101dfaa
Binary files /dev/null and b/indra/newview/installers/windows/lang_ru.nsi differ
diff --git a/indra/newview/installers/windows/lang_tr.nsi b/indra/newview/installers/windows/lang_tr.nsi
new file mode 100644
index 0000000000000000000000000000000000000000..bae5029ad1ce56a2fd347c95de656848400c052e
Binary files /dev/null and b/indra/newview/installers/windows/lang_tr.nsi differ
diff --git a/indra/newview/installers/windows/lang_zh.nsi b/indra/newview/installers/windows/lang_zh.nsi
new file mode 100644
index 0000000000000000000000000000000000000000..7922d9df5228d652bf08955f00c0eb62b6794965
Binary files /dev/null and b/indra/newview/installers/windows/lang_zh.nsi differ
diff --git a/indra/newview/installers/windows/language_menu.nsi b/indra/newview/installers/windows/language_menu.nsi
new file mode 100644
index 0000000000000000000000000000000000000000..2f426a0f47c92aac0b8e17441243802da7ab79e7
Binary files /dev/null and b/indra/newview/installers/windows/language_menu.nsi differ
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index fee3068c820c22b9ed65b872ec4cdabec1663ba6..5d5ae15901ba7bca89f9fc77480f42c017f47846 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -29,9 +29,6 @@
 #include "llappviewer.h"
 
 // Viewer includes
-#if LL_WINDOWS
-#include "alsquirrelupdater.h"
-#endif
 #include "llregex.h"
 #include "llversioninfo.h"
 #include "llfeaturemanager.h"
@@ -1142,13 +1139,7 @@ bool LLAppViewer::init()
     // Skip updater if this is a non-interactive instance
     if (!gSavedSettings.getBOOL("CmdLineSkipUpdater") && !gNonInteractive)
     {
-#if LL_WINDOWS
-		// Init updater here
-		if (ALUpdateHandler::isSupported())
-		{
-			ALUpdateHandler::getInstance()->check();
-		}
-#endif
+
     }
     else
     {
@@ -2568,12 +2559,6 @@ bool LLAppViewer::initConfiguration()
 		return false;
 	}
 
-#if LL_WINDOWS
-	if (ALUpdateUtils::handleCommandLineParse(clp))
-	{
-		return false;
-	}
-#endif
 	// - selectively apply settings
 
 	// If the user has specified a alternate settings file name.
@@ -3187,7 +3172,7 @@ LLSD LLAppViewer::getViewerInfo() const
 	LLSD info;
 	auto& versionInfo(LLVersionInfo::instance());
 	info["VIEWER_VERSION"] = llsd::array(versionInfo.getMajor(), versionInfo.getMinor(),
-										 versionInfo.getPatch());
+										 versionInfo.getPatch(), versionInfo.getBuild());
 	info["VIEWER_VERSION_STR"] = versionInfo.getVersion();
 	info["CHANNEL"] = versionInfo.getChannel();
 	info["ADDRESS_SIZE"] = ADDRESS_SIZE;
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index 8c496e4095bd4652d908f9349ddbcdf8369d41cd..0e308123fbf817d9f5cdc3a285536cd3b2801356 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -745,7 +745,7 @@ void LLAppViewerWin32::initCrashReporting(bool reportFreeze)
 	sentry_options_set_dsn(options, SENTRY_DSN);
 	sentry_options_set_release(options, LL_VIEWER_CHANNEL_AND_VERSION);
 
-	std::string crashpad_path = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "sentry", "crashpad_handler.exe");
+	std::string crashpad_path = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "crashpad_handler.exe");
 	sentry_options_set_handler_pathw(options, ll_convert_string_to_wide(crashpad_path).c_str());
 
 	std::string database_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "sentry");
diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp
index 097598af3a65fd70f57f2c8b72ad422c8c539f46..646d9a670e48f9e829b7488a68de2afa0c9a3779 100644
--- a/indra/newview/llfloaterabout.cpp
+++ b/indra/newview/llfloaterabout.cpp
@@ -32,9 +32,6 @@
 #include "llfloaterabout.h"
 
 // Viewer includes
-#if LL_WINDOWS
-#include "alsquirrelupdater.h"
-#endif
 #include "llagent.h"
 #include "llagentui.h"
 #include "llappviewer.h"
@@ -359,12 +356,7 @@ void LLFloaterAbout::onClickCopyToClipboard()
 
 void LLFloaterAbout::onClickUpdateCheck()
 {
-#if LL_WINDOWS
-	if (ALUpdateHandler::isSupported())
-	{
-		ALUpdateHandler::getInstance()->check();
-	}
-#endif
+
 }
 
 void LLFloaterAbout::setSupportText(const std::string& server_release_notes_url)
diff --git a/indra/newview/llversioninfo.cpp b/indra/newview/llversioninfo.cpp
index c9e8e9b5c9755dc5dd94363d06bdf94bae450566..4c8c73fa188089b0a013f791f5cdeaf53421b6c0 100644
--- a/indra/newview/llversioninfo.cpp
+++ b/indra/newview/llversioninfo.cpp
@@ -35,7 +35,8 @@
 #if ! defined(LL_VIEWER_CHANNEL)       \
  || ! defined(LL_VIEWER_VERSION_MAJOR) \
  || ! defined(LL_VIEWER_VERSION_MINOR) \
- || ! defined(LL_VIEWER_VERSION_PATCH)
+ || ! defined(LL_VIEWER_VERSION_PATCH) \
+ || ! defined(LL_VIEWER_VERSION_BUILD)
  #error "Channel or Version information is undefined"
 #endif
 
@@ -93,7 +94,7 @@ S32 LLVersionInfo::getPatch()
 
 S32 LLVersionInfo::getBuild()
 {
-	return 0;
+	return LL_VIEWER_VERSION_BUILD;
 }
 
 const std::string& LLVersionInfo::getVersion()
@@ -111,7 +112,7 @@ const std::string& LLVersionInfo::getChannelAndVersion()
 	if (mVersionChannel.empty())
 	{
 		// cache the version string
-		mVersionChannel = getChannel() + " " + getShortVersion();
+		mVersionChannel = getChannel() + " " + getVersion();
 	}
 
 	return mVersionChannel;
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index 2f76239c48d9cf9ac2de3e3a51b241486933e59e..40a86cc667d651b0838631f97644f22241f1dbe3 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -964,7 +964,7 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon()
 #if LL_WINDOWS
         // On windows use exe (not work or RO) directory
         std::string exe_path = gDirUtilp->getExecutableDir();
-        gDirUtilp->append(exe_path, "voice", "SLVoice.exe");
+        gDirUtilp->append(exe_path, "SLVoice.exe");
 #elif LL_DARWIN
         // On MAC use resource directory
         std::string exe_path = gDirUtilp->getAppRODataDir();
diff --git a/indra/newview/res/viewerRes.rc b/indra/newview/res/viewerRes.rc
index 09a518d28b6c68a4358d524770abeaa1c075a73d..5f4234c1bc8f41486bd2c0822672addba75e23c3 100755
--- a/indra/newview/res/viewerRes.rc
+++ b/indra/newview/res/viewerRes.rc
@@ -135,8 +135,8 @@ TOOLNO                  CURSOR                  "llno.cur"
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION ${VIEWER_VERSION_MAJOR},${VIEWER_VERSION_MINOR},${VIEWER_VERSION_PATCH},0
- PRODUCTVERSION ${VIEWER_VERSION_MAJOR},${VIEWER_VERSION_MINOR},${VIEWER_VERSION_PATCH},0
+ FILEVERSION ${VIEWER_VERSION_MAJOR},${VIEWER_VERSION_MINOR},${VIEWER_VERSION_PATCH},${VIEWER_VERSION_REVISION}
+ PRODUCTVERSION ${VIEWER_VERSION_MAJOR},${VIEWER_VERSION_MINOR},${VIEWER_VERSION_PATCH},${VIEWER_VERSION_REVISION}
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -153,13 +153,12 @@ BEGIN
         BEGIN
             VALUE "CompanyName", "Alchemy Development Group"
             VALUE "FileDescription", "${WIN_PRODUCT_NAME}"
-            VALUE "FileVersion", "${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}"
+            VALUE "FileVersion", "${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}.${VIEWER_VERSION_REVISION}"
             VALUE "InternalName", "${WIN_BINARY_NAME}"
             VALUE "LegalCopyright", "Copyright (C) 2013-2023 Alchemy Development Group"
             VALUE "OriginalFilename", "${WIN_BINARY_NAME}.exe"
             VALUE "ProductName", "${WIN_PRODUCT_NAME}"
-            VALUE "ProductVersion", "${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}"
-            VALUE "SquirrelAwareVersion", "1"
+            VALUE "ProductVersion", "${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}.${VIEWER_VERSION_REVISION}"
         END
     END
     BLOCK "VarFileInfo"
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 3536bdd55222e0aca6d5067913a13cb03aa6433e..662764fded7d7381e37c66159f126f0bcd20b488 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -12903,62 +12903,4 @@ Would you like to reset the graphic preferences?
   canceltext="Never reset"/>
  </notification>
 
-  <notification
-   icon="alertmodal.tga"
-   name="UpdateDownloadRequest"
-   type="alertmodal">
-A new version has been detected.
-Would you like to download and install [VIEWER_VER] with following updates now?
-
-[VIEWER_UPDATES]
-    <tag>confirm</tag>
-    <usetemplate
-     name="okcancelbuttons"
-     notext="Remind Me Later"
-     yestext="Ok"/>
-  </notification>
-
-  <notification
-   icon="alertmodal.tga"
-   name="UpdateDownloaded"
-   type="alertmodal">
-[VIEWER_VER] has been downloaded.
-Would you like to install [VIEWER_VER] for following updates now?
-
-[VIEWER_UPDATES]
-    <tag>confirm</tag>
-    <usetemplate
-     name="okcancelbuttons"
-     notext="Remind Me Later"
-     yestext="Ok"/>
-  </notification>
-
-  <notification
-   icon="alertmodal.tga"
-   name="UpdateInstalledRestart"
-   type="alertmodal">
-Your viewer has been updated to the following version:
-[VIEWER_VER] => [VIEWER_UPDATES] 
-
-Would you like to restart now?
-    <tag>confirm</tag>
-    <usetemplate
-     name="okcancelbuttons"
-     notext="Remind Me Later"
-     yestext="Ok"/>
-  </notification>
-  <notification
-   icon="notify.tga"
-   name="UpdateInstalledRestartToast"
-   type="notify">
-Your viewer has been updated to the following version:
-[VIEWER_VER] => [VIEWER_UPDATES] 
-
-Would you like to restart now?
-    <tag>confirm</tag>
-    <usetemplate
-     name="okcancelbuttons"
-     notext="Remind Me Later"
-     yestext="Ok"/>
-  </notification>
 </notifications>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 51853edc362189eda7b46ace718b5009f0b531a6..470036ee1bad6d84b433d9e901a665480de035a2 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -35,7 +35,7 @@
 
 	<!-- about dialog/support string-->
 	<string name="AboutHeader">
-[CHANNEL] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2] ([ADDRESS_SIZE]bit)
+[CHANNEL] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2].[VIEWER_VERSION_3] ([ADDRESS_SIZE]bit)
 [[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]]
 	</string>
 	<string name="AboutCompiler">Compiler Version: [COMPILER] [COMPILER_VERSION]</string>
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index f74a901b63ae2a6d509ae7bd8462b256257412a2..47dad6cacf212d67e4a976ea59bd4b84dfb45190 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -443,11 +443,14 @@ def construct(self):
         relpkgdir = os.path.join(pkgdir, "lib", "release")
         debpkgdir = os.path.join(pkgdir, "lib", "debug")
 
+        if self.is_packaging_viewer():
+            # Find alchemy-bin.exe in the 'configuration' dir, then rename it to the result of final_exe.
+            self.path(src='%s/alchemy-bin.exe' % self.args['configuration'], dst=self.final_exe())
+
         # Plugin host application
-        with self.prefix(dst="llplugin"):
-            self.path2basename(os.path.join(os.pardir,
-                                            'llplugin', 'slplugin', self.args['configuration']),
-                                            "slplugin.exe")
+        self.path2basename(os.path.join(os.pardir,
+                                        'llplugin', 'slplugin', self.args['configuration']),
+                           "slplugin.exe")
         
         # Get shared libs from the shared libs staging directory
         with self.prefix(src=os.path.join(self.args['build'], os.pardir,
@@ -469,22 +472,21 @@ def construct(self):
                     self.path(src="fmod.dll", dst="fmod.dll")
 
             # SLVoice executable
-            with self.prefix(dst="voice"):
-                with self.prefix(src=os.path.join(pkgdir, 'bin', 'release')):
-                    self.path("SLVoice.exe")
+            with self.prefix(src=os.path.join(pkgdir, 'bin', 'release')):
+                self.path("SLVoice.exe")
 
-                # Vivox libraries
-                if (self.address_size == 64):
-                    self.path("vivoxsdk_x64.dll")
-                    self.path("ortp_x64.dll")
-                else:
-                    self.path("vivoxsdk.dll")
-                    self.path("ortp.dll")
+            # Vivox libraries
+            if (self.address_size == 64):
+                self.path("vivoxsdk_x64.dll")
+                self.path("ortp_x64.dll")
+            else:
+                self.path("vivoxsdk.dll")
+                self.path("ortp.dll")
 
             # Sentry
             if self.args['sentry'] == 'ON' or self.args['sentry'] == 'TRUE':
                 self.path("sentry.dll")
-                with self.prefix(src=os.path.join(pkgdir, 'bin', 'release'), dst="sentry"):
+                with self.prefix(src=os.path.join(pkgdir, 'bin', 'release')):
                     self.path("crashpad_handler.exe")
 
             if self.args['discord'] == 'ON' or self.args['discord'] == 'TRUE':
@@ -598,58 +600,142 @@ def construct(self):
         if not self.is_packaging_viewer():
             self.package_file = "copied_deps"    
 
-    def package_finish(self):
-        nuget_exe = os.path.join(self.args['build'], os.pardir, 'packages', 'squirrel', 'nuget.exe')
-        self.run_command(
-            [nuget_exe,
-                'pack',
-                '-Properties', 'NoWarn=NU5128',
-                os.path.join(self.args['build'], 'viewer.nuspec')])
-
-        #Build installer and update delta
-        squirrel_exe = os.path.join(self.args['build'], os.pardir, 'packages', 'squirrel', 'Squirrel.exe')
-
-        # Download previous build for delta generation
-        temp_installdir = os.path.join(self.args['build'], 'Installer')
-        self.cmakedirs(temp_installdir)
-        if 'gendelta' in self.args and 'updateurl' in self.args:
-            if (self.address_size == 64):
-                updater_arch = 'x64'
+    def nsi_file_commands(self, install=True):
+        def wpath(path):
+            if path.endswith('/') or path.endswith(os.path.sep):
+                path = path[:-1]
+            path = path.replace('/', '\\')
+            return path
+
+        result = ""
+        dest_files = [pair[1] for pair in self.file_list if pair[0] and os.path.isfile(pair[1])]
+        # sort deepest hierarchy first
+        dest_files.sort(key=lambda f: (f.count(os.path.sep), f), reverse=True)
+        out_path = None
+        for pkg_file in dest_files:
+            rel_file = os.path.normpath(pkg_file.replace(self.get_dst_prefix()+os.path.sep,''))
+            installed_dir = wpath(os.path.join('$INSTDIR', os.path.dirname(rel_file)))
+            pkg_file = wpath(os.path.normpath(pkg_file))
+            if installed_dir != out_path:
+                if install:
+                    out_path = installed_dir
+                    result += 'SetOutPath ' + out_path + '\n'
+            if install:
+                result += 'File ' + pkg_file + '\n'
             else:
-                updater_arch = 'x86'
+                result += 'Delete ' + wpath(os.path.join('$INSTDIR', rel_file)) + '\n'
+
+        # at the end of a delete, just rmdir all the directories
+        if not install:
+            deleted_file_dirs = [os.path.dirname(pair[1].replace(self.get_dst_prefix()+os.path.sep,'')) for pair in self.file_list]
+            # find all ancestors so that we don't skip any dirs that happened to have no non-dir children
+            deleted_dirs = []
+            for d in deleted_file_dirs:
+                deleted_dirs.extend(path_ancestors(d))
+            # sort deepest hierarchy first
+            deleted_dirs.sort(key=lambda f: (f.count(os.path.sep), f), reverse=True)
+            prev = None
+            for d in deleted_dirs:
+                if d != prev:   # skip duplicates
+                    result += 'RMDir ' + wpath(os.path.join('$INSTDIR', os.path.normpath(d))) + '\n'
+                prev = d
+
+        return result
 
-            try:
-                self.run_command(
-                    [squirrel_exe,
-                        'http-down',
-                        '--releaseDir', temp_installdir,
-                        '--url', '{}/{}/win-{}/'.format(self.args['updateurl'], self.app_name_oneword(), updater_arch)])
-            except (ManifestError, MissingError) as err:
-                pass
+    def package_finish(self):
+        # a standard map of strings for replacing in the templates
+        substitution_strings = {
+            'version' : '.'.join(self.args['version']),
+            'version_short' : '.'.join(self.args['version'][:-1]),
+            'version_dashes' : '-'.join(self.args['version']),
+            'version_registry' : '%s(%s)' %
+            ('.'.join(self.args['version']), self.address_size),
+            'final_exe' : self.final_exe(),
+            'flags':'',
+            'app_name':self.app_name(),
+            'app_name_oneword':self.app_name_oneword()
+            }
 
-        # Build installer files
-        temp_nupkg = os.path.join(self.args['build'], '{}.{}.nupkg'.format(self.app_name_oneword(), '.'.join(self.args['version'])))
-        self.run_command(
-            [squirrel_exe,
-                'releasify',
-                '--releaseDir', temp_installdir,
-                '--framework', 'vcredist143-x64',
-                '--icon', os.path.join(self.args['source'], 'installers', 'windows', 'install_icon.ico'),
-                '--splashImage', os.path.join(self.args['source'], 'installers', 'windows', 'install_splash.gif'),
-                '--package', temp_nupkg])
-
-        # Copy to final installer destination
         installer_file = self.installer_base_name() + '_Setup.exe'
-        with self.prefix(src=temp_installdir, dst=os.path.join(self.args['build'], 'Deploy')):  # everything goes in Contents
-            self.path(src=self.app_name_oneword() + 'Setup.exe', dst=installer_file)
-            self.path('{}-{}-*.nupkg'.format(self.app_name_oneword(), '.'.join(self.args['version'])))
-            self.path('RELEASES')
-
-        # Clean up temporary files
-        os.remove(temp_nupkg)
-        shutil.rmtree(temp_installdir, True)
+        substitution_strings['installer_file'] = installer_file
+        
+        version_vars = """
+        !define INSTEXE "SLVersionChecker.exe"
+        !define VERSION "%(version_short)s"
+        !define VERSION_LONG "%(version)s"
+        !define VERSION_DASHES "%(version_dashes)s"
+        !define VERSION_REGISTRY "%(version_registry)s"
+        !define VIEWER_EXE "%(final_exe)s"
+        """ % substitution_strings
+        
+        if self.channel_type() == 'release':
+            substitution_strings['caption'] = CHANNEL_VENDOR_BASE
+        else:
+            substitution_strings['caption'] = self.app_name() + ' ${VERSION}'
+
+        inst_vars_template = """
+            OutFile "%(installer_file)s"
+            !define INSTNAME   "%(app_name_oneword)s"
+            !define SHORTCUT   "%(app_name)s"
+            !define URLNAME   "secondlife"
+            Caption "%(caption)s"
+            """
+
+        if(self.address_size == 64):
+            engage_registry="SetRegView 64"
+            program_files="!define MULTIUSER_USE_PROGRAMFILES64"
+        else:
+            engage_registry="SetRegView 32"
+            program_files=""
+
+        tempfile = "alchemy_setup_tmp.nsi"
+        # the following replaces strings in the nsi template
+        # it also does python-style % substitution
+        self.replace_in("installers/windows/installer_template.nsi", tempfile, {
+                "%%VERSION%%":version_vars,
+                "%%SOURCE%%":self.get_src_prefix(),
+                "%%INST_VARS%%":inst_vars_template % substitution_strings,
+                "%%INSTALL_FILES%%":self.nsi_file_commands(True),
+                "%%PROGRAMFILES%%":program_files,
+                "%%ENGAGEREGISTRY%%":engage_registry,
+                "%%DELETE_FILES%%":self.nsi_file_commands(False)})
+
+        # If we're on a build machine, sign the code using our Authenticode certificate. JC
+        # note that the enclosing setup exe is signed later, after the makensis makes it.
+        # Unlike the viewer binary, the VMP filenames are invariant with respect to version, os, etc.
+        for exe in (
+            self.final_exe(),
+            "SLVersionChecker.exe",
+            "llplugin/dullahan_host.exe",
+            ):
+            self.sign(exe)
+            
+        # Check two paths, one for Program Files, and one for Program Files (x86).
+        # Yay 64bit windows.
+        for ProgramFiles in 'ProgramFiles', 'ProgramFiles(x86)':
+            NSIS_path = os.path.expandvars(r'${%s}\NSIS\makensis.exe' % ProgramFiles)
+            if os.path.exists(NSIS_path):
+                break
+        installer_created=False
+        nsis_attempts=3
+        nsis_retry_wait=15
+        for attempt in range(nsis_attempts):
+            try:
+                self.run_command([NSIS_path, '/V2', self.dst_path_of(tempfile)])
+            except ManifestError as err:
+                if attempt+1 < nsis_attempts:
+                    print("nsis failed, waiting %d seconds before retrying" % nsis_retry_wait, file=sys.stderr)
+                    time.sleep(nsis_retry_wait)
+                    nsis_retry_wait*=2
+            else:
+                # NSIS worked! Done!
+                break
+        else:
+            print("Maximum nsis attempts exceeded; giving up", file=sys.stderr)
+            raise
 
-        self.created_path(os.path.join(self.args['build'], 'Deploy', installer_file))
+        self.sign(installer_file)
+        self.created_path(self.dst_path_of(installer_file))
         self.package_file = installer_file
 
     def sign(self, exe):