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/.gitlab-ci.yml b/.gitlab-ci.yml
index 6f3a0251bee68bc80d235223b5558bbb0f2a75fc..25474fd1485c75fbf275ac30f37a7287303a14eb 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -75,16 +75,16 @@ variables:
     - .\.venv\Scripts\Activate.ps1
     - pip install --upgrade llbase autobuild certifi sentry-cli cmake
   script:
-    - autobuild configure -c Release -- -DUSE_LTO="${ENABLE_LTO}" -DHAVOK_TPV="${USE_HAVOK}" -DLL_TESTS="${ENABLE_TESTS}" -DDISABLE_FATAL_WARNINGS=ON -DREVISION_FROM_VCS=FALSE -DENABLE_DELTA_GEN=ON
+    - autobuild configure -c Release -- -DUSE_LTO="${ENABLE_LTO}" -DHAVOK_TPV="${USE_HAVOK}" -DLL_TESTS="${ENABLE_TESTS}" -DDISABLE_FATAL_WARNINGS=ON -DREVISION_FROM_VCS=FALSE
     - autobuild build -c Release --no-configure
     - autobuild graph -c Release --graph-file "alchemy-windows${AUTOBUILD_ADDRSIZE}-dependencies.svg" "build-vc-${AUTOBUILD_ADDRSIZE}/autobuild-package.xml"
-    - If ($env:USE_SENTRY -eq 'TRUE') { sentry-cli debug-files upload --include-sources (Get-Item .\build-vc-${AUTOBUILD_ADDRSIZE}\newview\Release\Alchemy*.*).FullName (Get-Item .\build-vc-64\newview\Release\*.dll).FullName }
+    - If ($env:USE_SENTRY -eq 'TRUE') { sentry-cli debug-files upload --include-sources (Get-Item .\build-vc-${AUTOBUILD_ADDRSIZE}\newview\Release\alchemy-bin.*).FullName (Get-Item .\build-vc-64\newview\Release\*.dll).FullName }
   artifacts:
     name: "$env:CI_COMMIT_REF_NAME-$env:CI_COMMIT_SHORT_SHA"
     expire_in: 1 week
     paths:
       - build-vc-*/newview/Release/build_data.json
-      - build-vc-*/newview/Deploy/*
+      - build-vc-*/newview/Release/Alchemy_*_Setup.exe
       - alchemy-*-dependencies.svg
 
 .mac_build:
@@ -396,21 +396,13 @@ build:release:windows64:
     - Pop-Location
 
     - Push-Location ./build-vc-64/
-    -   Push-Location ./newview/Deploy/
+    -   Push-Location ./newview/Release/
     -     $WinFileName = Get-ChildItem -Path . -Name -Include Alchemy_*_Setup.exe
     -     $WinFileHash = (Get-FileHash .\$WinFileName -a sha256).Hash
     -     $WinPackageUrl = "${UploadDestURL}/${WinFileName}"
     -     $WinUploadResult = Invoke-WebRequest @UploadParams -InFile ./$WinFileName -Uri "${WinPackageUrl}${DestStatus}" -MaximumRetryCount 5 -RetryIntervalSec 30 | ConvertFrom-Json
     -     If ($WinFileHash -ne $WinUploadResult.file_sha256) { Write-Output "Upload hash mismatch. expected $Hash actual $($WinUploadResult.file_sha256)" && Exit 1 }
 
-    -     $WinUpdateDeployURL = "${UpdateDeployDestURL}/win-x64"
-    -     $FullUpdatePkg = Get-ChildItem -Path . -Name -Include Alchemy*-full.nupkg
-    -     if (Test-Path -Path ./Alchemy*-full.nupkg) { Invoke-WebRequest @UploadParams -InFile ./$FullUpdatePkg -Uri "${WinUpdateDeployURL}/${FullUpdatePkg}" -MaximumRetryCount 5 -RetryIntervalSec 30 }
-    -     $DeltaUpdatePkg = Get-ChildItem -Path . -Name -Include Alchemy*-delta.nupkg
-    -     if (Test-Path -Path ./Alchemy*-delta.nupkg) { Invoke-WebRequest @UploadParams -InFile ./$DeltaUpdatePkg -Uri "${WinUpdateDeployURL}/${DeltaUpdatePkg}" -MaximumRetryCount 5 -RetryIntervalSec 30 }
-    -     $ReleaseFile = Get-ChildItem -Path . -Name -Include RELEASES
-    -     if (Test-Path -Path ./RELEASES) { Invoke-WebRequest @UploadParams -InFile ./$ReleaseFile -Uri "${WinUpdateDeployURL}/${ReleaseFile}" -MaximumRetryCount 5 -RetryIntervalSec 30 }
-
     -   Pop-Location
     - Pop-Location
     - If ($env:USE_SENTRY -eq 'TRUE') { sentry-cli releases finalize $BuildChannelVersion }
diff --git a/autobuild.xml b/autobuild.xml
index ff9768828b92997fc0c10bba14c4587fe09966bd..bf52db0031a8f7e1e41c3b6fe7ec8b158efae95c 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -819,6 +819,38 @@
         <key>version</key>
         <string>0.10.6.314267</string>
       </map>
+      <key>innosetup</key>
+      <map>
+        <key>copyright</key>
+        <string>Copyright (C) 1997-2023 Jordan Russell. All rights reserved.</string>
+        <key>description</key>
+        <string>Innosetup installer framework</string>
+        <key>license</key>
+        <string>MIT</string>
+        <key>license_file</key>
+        <string>LICENSES/innosetup.txt</string>
+        <key>name</key>
+        <string>innosetup</string>
+        <key>platforms</key>
+        <map>
+          <key>windows64</key>
+          <map>
+            <key>archive</key>
+            <map>
+              <key>hash</key>
+              <string>46b82a3209dfa4bc6b65aa655eebdbd4ecaed1e1cc33e0a3b77d36475d5fa3ccd3fdc220c803ba91fa19b3e94b3bda2fa459cabab2620946af28f170d8aaa76c</string>
+              <key>hash_algorithm</key>
+              <string>blake2b</string>
+              <key>url</key>
+              <string>https://git.alchemyviewer.org/api/v4/projects/212/packages/generic/innosetup/6.2.2.2143/innosetup-6.2.2-windows64-2143.tar.zst</string>
+            </map>
+            <key>name</key>
+            <string>windows64</string>
+          </map>
+        </map>
+        <key>version</key>
+        <string>6.2.2</string>
+      </map>
       <key>jpegencoderbasic</key>
       <map>
         <key>copyright</key>
@@ -2079,38 +2111,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
         <key>version</key>
         <string>4.10.0000.32327.5fc3fe7c.558436</string>
       </map>
-      <key>squirrel</key>
-      <map>
-        <key>copyright</key>
-        <string>Copyright (c) 2012 GitHub, Inc.</string>
-        <key>description</key>
-        <string>Squirrel installer framework</string>
-        <key>license</key>
-        <string>MIT</string>
-        <key>license_file</key>
-        <string>LICENSES/squirrel.txt</string>
-        <key>name</key>
-        <string>squirrel</string>
-        <key>platforms</key>
-        <map>
-          <key>windows64</key>
-          <map>
-            <key>archive</key>
-            <map>
-              <key>hash</key>
-              <string>6ebc2d8934207911406aea18de8eac46bcd18cc4b6f6e2c24b936cac2d7f0abe94fc17e274f5567dc4280ace5a4e8accac658edb0cdf0623348fc72678c999cd</string>
-              <key>hash_algorithm</key>
-              <string>blake2b</string>
-              <key>url</key>
-              <string>https://git.alchemyviewer.org/api/v4/projects/197/packages/generic/squirrel/2.9.42.1850/squirrel-2.9.42-windows64-1850.tar.zst</string>
-            </map>
-            <key>name</key>
-            <string>windows64</string>
-          </map>
-        </map>
-        <key>version</key>
-        <string>2.9.42</string>
-      </map>
       <key>threejs</key>
       <map>
         <key>copyright</key>
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/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake
index 222017c55fec6ba54f142a10add144ba03d0cefd..79274a9a0f76c0015fcc2467898d7bafa9c99bc5 100644
--- a/indra/cmake/Copy3rdPartyLibs.cmake
+++ b/indra/cmake/Copy3rdPartyLibs.cmake
@@ -85,6 +85,68 @@ if(WINDOWS)
     if(TARGET al::discord-gamesdk)
       list(APPEND release_files discord_game_sdk.dll)
     endif()
+
+    #*******************************
+    # Copy MS C runtime dlls, required for packaging.
+    if (MSVC80)
+        set(MSVC_VER 80)
+    elseif (MSVC_VERSION EQUAL 1600) # VisualStudio 2010
+        MESSAGE(STATUS "MSVC_VERSION ${MSVC_VERSION}")
+    elseif (MSVC_VERSION EQUAL 1800) # VisualStudio 2013, which is (sigh) VS 12
+        set(MSVC_VER 120)
+    elseif (MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1920) # Visual Studio 2017
+        set(MSVC_VER 140)
+    elseif (MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1930) # Visual Studio 2019
+        set(MSVC_VER 140)
+    elseif (MSVC_VERSION GREATER_EQUAL 1930 AND MSVC_VERSION LESS 1940) # Visual Studio 2022
+        set(MSVC_VER 140)
+    else (MSVC80)
+        MESSAGE(WARNING "New MSVC_VERSION ${MSVC_VERSION} of MSVC: adapt Copy3rdPartyLibs.cmake")
+    endif (MSVC80)
+
+    if(ADDRESS_SIZE EQUAL 32)
+        # this folder contains the 32bit DLLs.. (yes really!)
+        set(registry_find_path "[HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Windows;Directory]/SysWOW64")
+    else(ADDRESS_SIZE EQUAL 32)
+        # this folder contains the 64bit DLLs.. (yes really!)
+        set(registry_find_path "[HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Windows;Directory]/System32")
+    endif(ADDRESS_SIZE EQUAL 32)
+
+    # Having a string containing the system registry path is a start, but to
+    # get CMake to actually read the registry, we must engage some other
+    # operation.
+    get_filename_component(registry_path "${registry_find_path}" ABSOLUTE)
+
+    # These are candidate DLL names. Empirically, VS versions before 2015 have
+    # msvcp*.dll and msvcr*.dll. VS 2017 has msvcp*.dll and vcruntime*.dll.
+    # Check each of them.
+    foreach(release_msvc_file
+            concrt${MSVC_VER}.dll
+            msvcp${MSVC_VER}.dll
+            msvcp${MSVC_VER}_1.dll
+            msvcp${MSVC_VER}_2.dll
+            msvcp${MSVC_VER}_atomic_wait.dll
+            msvcp${MSVC_VER}_codecvt_ids.dll
+            vccorlib${MSVC_VER}.dll
+            vcruntime${MSVC_VER}.dll
+            vcruntime${MSVC_VER}_1.dll
+            )
+        if(EXISTS "${registry_path}/${release_msvc_file}")
+            to_staging_dirs(
+                ${registry_path}
+                third_party_targets
+                ${release_msvc_file})
+        else()
+            # This isn't a WARNING because, as noted above, every VS version
+            # we've observed has only a subset of the specified DLL names.
+            MESSAGE(STATUS "Redist lib ${release_msvc_file} not found")
+        endif()
+    endforeach()
+    MESSAGE(STATUS "Will copy redist files for MSVC ${MSVC_VER}:")
+    foreach(target ${third_party_targets})
+        MESSAGE(STATUS "${target}")
+    endforeach()
+
 elseif(DARWIN)
     set(vivox_lib_dir "${ARCH_PREBUILT_DIRS_RELEASE}")
     set(slvoice_files SLVoice)
@@ -136,7 +198,7 @@ elseif(LINUX)
          list( APPEND release_files
                  libjpeg.so
                  libjpeg.so.8
-                 libjpeg.so.8.2.2
+                 libjpeg.so.8.3.2
                  )
      endif()
 
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..89325f65a3de4f96d3c924c9636f696d189bbf46 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -52,8 +52,9 @@ include(LLPrimitive)
 
 # Viewer Branding Assets
 use_prebuilt_binary(branding)
-if (WINDOWS)
-  use_prebuilt_binary(squirrel)
+
+if(WINDOWS)
+  use_prebuilt_binary(innosetup)
 endif()
 
 if( LLPHYSICSEXTENSIONS_SRC_DIR )
@@ -1531,12 +1532,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 +1639,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 +1707,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 +1757,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 +1879,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 +2011,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 +2032,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 +2138,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 +2219,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 +2371,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/install_template.iss b/indra/newview/installers/windows/install_template.iss
new file mode 100644
index 0000000000000000000000000000000000000000..a11bcb5ea9b67406d9523a818f2b844b06df29c3
--- /dev/null
+++ b/indra/newview/installers/windows/install_template.iss
@@ -0,0 +1,111 @@
+; Script generated by the Inno Setup Script Wizard.
+; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
+
+;#define MyAppName "Alchemy Viewer"
+;#define MyAppNameShort "AlchemyViewer"
+;#define MyAppVersion "7.0.0.4545"
+;#define MyAppExeName "MyProg.exe"
+;#define ViewerSrcDir ""
+
+%%INST_VARS%%
+
+#define MyAppPublisher "Alchemy Development Group"
+#define MyAppURL "https://www.alchemyviewer.org"
+
+[Setup]
+; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
+; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
+AppId={{564993A0-36C3-4C9C-83FA-336EAB720367}
+AppName={#MyAppName}
+AppVersion={#MyAppVersion}
+AppVerName={#MyAppName} {#MyAppVersion} 
+;AppVerName={#MyAppName} {#MyAppVersion}
+AppPublisher={#MyAppPublisher}
+AppPublisherURL={#MyAppURL}
+AppSupportURL={#MyAppURL}
+AppUpdatesURL={#MyAppURL}
+AppCopyright=Copyright (C) 2013-2023 {#MyAppPublisher}
+DefaultDirName={autopf}\{#MyAppNameShort}
+DisableProgramGroupPage=yes
+;LicenseFile={#ViewerSrcDir}\..\..\doc\LGPL-license.txt
+; Uncomment the following line to run in non administrative install mode (install for current user only.)
+;PrivilegesRequired=lowest
+PrivilegesRequiredOverridesAllowed=commandline
+OutputDir=.
+OutputBaseFilename={#MyAppInstFile}
+SetupIconFile={#ViewerSrcDir}\installers\windows\install_icon.ico
+Compression=lzma2
+SolidCompression=yes
+WizardStyle=modern
+ArchitecturesAllowed=x64
+ArchitecturesInstallIn64BitMode=x64
+MinVersion=10.0
+AppMutex=AlchemyAppMutex,Global\AlchemyAppMutex
+VersionInfoCompany={#MyAppPublisher}
+VersionInfoVersion={#MyAppVersion}
+AlwaysShowDirOnReadyPage=yes
+UninstallDisplayIcon={app}\{#MyAppExeName}
+;DisableWelcomePage=no
+
+[Languages]
+Name: "english"; MessagesFile: "compiler:Default.isl"
+Name: "armenian"; MessagesFile: "compiler:Languages\Armenian.isl"
+Name: "brazilianportuguese"; MessagesFile: "compiler:Languages\BrazilianPortuguese.isl"
+Name: "bulgarian"; MessagesFile: "compiler:Languages\Bulgarian.isl"
+Name: "catalan"; MessagesFile: "compiler:Languages\Catalan.isl"
+Name: "corsican"; MessagesFile: "compiler:Languages\Corsican.isl"
+Name: "czech"; MessagesFile: "compiler:Languages\Czech.isl"
+Name: "danish"; MessagesFile: "compiler:Languages\Danish.isl"
+Name: "dutch"; MessagesFile: "compiler:Languages\Dutch.isl"
+Name: "finnish"; MessagesFile: "compiler:Languages\Finnish.isl"
+Name: "french"; MessagesFile: "compiler:Languages\French.isl"
+Name: "german"; MessagesFile: "compiler:Languages\German.isl"
+Name: "hebrew"; MessagesFile: "compiler:Languages\Hebrew.isl"
+Name: "hungarian"; MessagesFile: "compiler:Languages\Hungarian.isl"
+Name: "icelandic"; MessagesFile: "compiler:Languages\Icelandic.isl"
+Name: "italian"; MessagesFile: "compiler:Languages\Italian.isl"
+Name: "japanese"; MessagesFile: "compiler:Languages\Japanese.isl"
+Name: "norwegian"; MessagesFile: "compiler:Languages\Norwegian.isl"
+Name: "polish"; MessagesFile: "compiler:Languages\Polish.isl"
+Name: "portuguese"; MessagesFile: "compiler:Languages\Portuguese.isl"
+Name: "russian"; MessagesFile: "compiler:Languages\Russian.isl"
+Name: "slovak"; MessagesFile: "compiler:Languages\Slovak.isl"
+Name: "slovenian"; MessagesFile: "compiler:Languages\Slovenian.isl"
+Name: "spanish"; MessagesFile: "compiler:Languages\Spanish.isl"
+Name: "turkish"; MessagesFile: "compiler:Languages\Turkish.isl"
+Name: "ukrainian"; MessagesFile: "compiler:Languages\Ukrainian.isl"
+
+[Tasks]
+Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
+
+[Files]
+; NOTE: Don't use "Flags: ignoreversion" on any shared system files
+%%INSTALL_FILES%%
+
+[InstallDelete]
+Type: files; Name: "{app}\app_settings"
+Type: files; Name: "{app}\llplugin"
+Type: files; Name: "{app}\skins"
+
+[Icons]
+Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
+Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
+
+[Run]
+Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
+
+[Registry]
+Root: HKA; Subkey: "Software\Classes\secondlife"; ValueType: "string"; ValueData: "URL:Second Life"; Flags: uninsdeletekey
+Root: HKA; Subkey: "Software\Classes\secondlife"; ValueType: "string"; ValueName: "URL Protocol"; ValueData: ""
+Root: HKA; Subkey: "Software\Classes\secondlife\DefaultIcon"; ValueType: "string"; ValueData: "{app}\{#MyAppExeName},0"
+Root: HKA; Subkey: "Software\Classes\secondlife\shell\open\command"; ValueType: "string"; ValueData: """{app}\{#MyAppExeName}"" -url ""%1"""
+
+Root: HKA; Subkey: "Software\Classes\x-grid-info"; ValueType: "string"; ValueData: "URL:Hypergrid"; Flags: uninsdeletekey
+Root: HKA; Subkey: "Software\Classes\x-grid-info"; ValueType: "string"; ValueName: "URL Protocol"; ValueData: ""
+Root: HKA; Subkey: "Software\Classes\x-grid-info\DefaultIcon"; ValueType: "string"; ValueData: "{app}\{#MyAppExeName},0"
+Root: HKA; Subkey: "Software\Classes\x-grid-info\shell\open\command"; ValueType: "string"; ValueData: """{app}\{#MyAppExeName}"" -url ""%1"""
+
+Root: HKA; Subkey: "Software\Classes\x-grid-location-info"; ValueType: "string"; ValueData: "URL:Hypergrid"; Flags: uninsdeletekey
+Root: HKA; Subkey: "Software\Classes\x-grid-location-info"; ValueType: "string"; ValueName: "URL Protocol"; ValueData: ""
+Root: HKA; Subkey: "Software\Classes\x-grid-location-info\DefaultIcon"; ValueType: "string"; ValueData: "{app}\{#MyAppExeName},0"
+Root: HKA; Subkey: "Software\Classes\x-grid-location-info\shell\open\command"; ValueType: "string"; ValueData: """{app}\{#MyAppExeName}"" -url ""%1"""
\ No newline at end of file
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/llface.cpp b/indra/newview/llface.cpp
index 6c99f648dec5ed3074e914bfb90d6576b2d1eb3d..9c5de18a35c2e3f069f8945a47a010a2736f3169 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -1192,7 +1192,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 		{
 			if (gDebugGL)
 			{
-                llassert(false);
 				LL_WARNS()	<< "Index buffer overflow!" << LL_ENDL;
 				LL_WARNS() << "Indices Count: " << mIndicesCount
 						<< " VF Num Indices: " << num_indices
@@ -1200,6 +1199,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 						<< " VB Num Indices: " << mVertexBuffer->getNumIndices() << LL_ENDL;
 				LL_WARNS()	<< " Face Index: " << f
 						<< " Pool Type: " << mPoolType << LL_ENDL;
+				llassert(false);
 			}
 			return FALSE;
 		}
@@ -1208,8 +1208,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 		{
 			if (gDebugGL)
 			{
-                llassert(false);
 				LL_WARNS() << "Vertex buffer overflow!" << LL_ENDL;
+				llassert(false);
 			}
 			return FALSE;
 		}
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/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp
index 2f42067a518ad709662140cee39c9c978d5acea7..9c8a97eed1b52390fbf74795aac8f0766096e765 100644
--- a/indra/newview/llmaterialeditor.cpp
+++ b/indra/newview/llmaterialeditor.cpp
@@ -1204,10 +1204,16 @@ bool LLMaterialEditor::saveIfNeeded()
     }
     else
     { 
-        //make a new inventory item
-        std::string res_desc = buildMaterialDescription();
+        // Make a new inventory item and set upload permissions
         LLPermissions local_permissions;
         local_permissions.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null);
+
+        U32 everyone_perm = LLFloaterPerms::getEveryonePerms("Materials");
+        U32 group_perm = LLFloaterPerms::getGroupPerms("Materials");
+        U32 next_owner_perm = LLFloaterPerms::getNextOwnerPerms("Materials");
+        local_permissions.initMasks(PERM_ALL, PERM_ALL, everyone_perm, group_perm, next_owner_perm);
+
+        std::string res_desc = buildMaterialDescription();
         createInventoryItem(buffer, mMaterialName, res_desc, local_permissions);
 
         // We do not update floater with uploaded asset yet, so just close it.
@@ -1954,6 +1960,32 @@ bool LLMaterialEditor::canSaveObjectsMaterial()
     return can_use_objects_material(func, std::vector({PERM_COPY, PERM_MODIFY}), permissions, item_out);
 }
 
+bool LLMaterialEditor::canClipboardObjectsMaterial()
+{
+    if (LLSelectMgr::getInstance()->getSelection()->getObjectCount() != 1)
+    {
+        return false;
+    }
+
+    struct LLSelectedTEGetNullMat : public LLSelectedTEFunctor
+    {
+        bool apply(LLViewerObject* objectp, S32 te_index)
+        {
+            return objectp->getRenderMaterialID(te_index).isNull();
+        }
+    } null_func;
+
+    if (LLSelectMgr::getInstance()->getSelection()->applyToTEs(&null_func))
+    {
+        return true;
+    }
+
+    LLSelectedTEGetMatData func(true);
+    LLPermissions permissions;
+    LLViewerInventoryItem* item_out;
+    return can_use_objects_material(func, std::vector({PERM_COPY, PERM_MODIFY, PERM_TRANSFER}), permissions, item_out);
+}
+
 void LLMaterialEditor::saveObjectsMaterialAs()
 {
     LLSelectedTEGetMatData func(true);
diff --git a/indra/newview/llmaterialeditor.h b/indra/newview/llmaterialeditor.h
index 6b2f49e2fc6697cdce086e977049ce5671a0eeae..b29db706f819c93a01f3d59582c0471b3f8a4256 100644
--- a/indra/newview/llmaterialeditor.h
+++ b/indra/newview/llmaterialeditor.h
@@ -115,6 +115,7 @@ class LLMaterialEditor : public LLPreview, public LLVOInventoryListener
 
     static bool canModifyObjectsMaterial();
     static bool canSaveObjectsMaterial();
+    static bool canClipboardObjectsMaterial();
     static void saveObjectsMaterialAs();
     static void onCopyObjectsMaterialAsMsgCallback(const LLSD& notification, const LLSD& response, const LLPermissions& permissions, const LLUUID& object_id, const LLUUID& item_id);
     static void onSaveObjectsMaterialAsMsgCallback(const LLSD& notification, const LLSD& response, const LLPermissions& permissions);
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index 39dba3e3444c75874f91f3e22e0f75bff22fd3d7..8e4acb508f1d020eff67acd9f2c0f28902ed768d 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -1921,7 +1921,8 @@ void LLPanelFace::updateCopyTexButton()
     LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
     mMenuClipboardTexture->setEnabled(objectp && objectp->getPCode() == LL_PCODE_VOLUME && objectp->permModify() 
                                                     && !objectp->isPermanentEnforced() && !objectp->isInventoryPending() 
-                                                    && (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1));
+                                                    && (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1)
+                                                    && LLMaterialEditor::canClipboardObjectsMaterial());
     std::string tooltip = (objectp && objectp->isInventoryPending()) ? LLTrans::getString("LoadingContents") : getString("paste_options");
     mMenuClipboardTexture->setToolTip(tooltip);
 }
@@ -4054,7 +4055,8 @@ void LLPanelFace::onCopyTexture()
         || objectp->getPCode() != LL_PCODE_VOLUME
         || !objectp->permModify()
         || objectp->isPermanentEnforced()
-        || selected_count > 1)
+        || selected_count > 1
+        || !LLMaterialEditor::canClipboardObjectsMaterial())
     {
         return;
     }
@@ -4249,7 +4251,8 @@ void LLPanelFace::onPasteTexture()
         || objectp->getPCode() != LL_PCODE_VOLUME
         || !objectp->permModify()
         || objectp->isPermanentEnforced()
-        || selected_count > 1)
+        || selected_count > 1
+        || !LLMaterialEditor::canClipboardObjectsMaterial())
     {
         // not supposed to happen
         LL_WARNS() << "Failed to paste texture due to missing or wrong selection" << LL_ENDL;
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..7f618e126ebea6cb79284fe718677fc9cdea3f74 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,
@@ -468,23 +471,34 @@ def construct(self):
                 else:
                     self.path(src="fmod.dll", dst="fmod.dll")
 
+            # These need to be installed as a SxS assembly, currently a 'private' assembly.
+            # See http://msdn.microsoft.com/en-us/library/ms235291(VS.80).aspx
+            self.path("concrt140.dll")
+            self.path("msvcp140.dll")
+            self.path("msvcp140_1.dll")
+            self.path("msvcp140_2.dll")
+            self.path("msvcp140_atomic_wait.dll")
+            self.path("msvcp140_codecvt_ids.dll")
+            self.path("vccorlib140.dll")
+            self.path("vcruntime140.dll")
+            self.path("vcruntime140_1.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 +612,95 @@ 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'
-            else:
-                updater_arch = 'x86'
+    def isc_file_commands(self):
+        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('{app}', os.path.dirname(rel_file)))
+            pkg_file = wpath(os.path.normpath(pkg_file))
+            result += 'Source: "' + pkg_file + '"; DestDir: "' + installed_dir + '"; Flags: ignoreversion \n'
+
+        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(),
+            'src_dir':self.get_src_prefix()
+            }
 
-        # 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'] = self.installer_base_name() + '_Setup'
+        
+        if self.channel_type() == 'release':
+            substitution_strings['caption'] = CHANNEL_VENDOR_BASE
+        else:
+            substitution_strings['caption'] = self.app_name() + ' ${VERSION}'
+
+        inst_vars_template = """
+#define MyAppName "%(app_name)s"
+#define MyAppNameShort "%(app_name_oneword)s"
+#define MyAppVersion "%(version)s"
+#define MyAppExeName "%(final_exe)s"
+#define ViewerSrcDir "%(src_dir)s"
+#define MyAppInstFile "%(installer_file)s"
+            """
+
+        tempfile = "alchemy_setup_tmp.iss"
+        # the following replaces strings in the nsi template
+        # it also does python-style % substitution
+        self.replace_in("installers/windows/install_template.iss", tempfile, {
+                "%%SOURCE%%":self.get_src_prefix(),
+                "%%INST_VARS%%":inst_vars_template % substitution_strings,
+                "%%INSTALL_FILES%%":self.isc_file_commands()})
+
+        # 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(),
+            "llplugin/dullahan_host.exe",
+            ):
+            self.sign(exe)
+            
+        inno_path = os.path.join(self.args['build'], os.pardir, 'packages', 'innosetup', 'iscc.exe')
+        iscc_attempts=3
+        iscc_retry_wait=15
+        for attempt in range(iscc_attempts):
+            try:
+                self.run_command([inno_path, self.dst_path_of(tempfile)])
+            except ManifestError as err:
+                if attempt+1 < iscc_attempts:
+                    print("iscc failed, waiting %d seconds before retrying" % iscc_retry_wait, file=sys.stderr)
+                    time.sleep(iscc_retry_wait)
+                    iscc_retry_wait*=2
+            else:
+                # ISCC worked! Done!
+                break
+        else:
+            print("Maximum iscc 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):