summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Repository.mk1
-rw-r--r--RepositoryExternal.mk4
-rw-r--r--config_host.mk.in3
-rw-r--r--configure.ac44
-rw-r--r--external/msc-externals/Module_msc-externals.mk6
-rw-r--r--external/msc-externals/Package_ucrt.mk (renamed from external/msc-externals/Package_vcredist_exe.mk)11
-rw-r--r--instsetoo_native/inc_ooohelppack/windows/msi_templates/Control.idt2
-rw-r--r--instsetoo_native/inc_openoffice/windows/msi_languages/CustomAc.ulf3
-rw-r--r--instsetoo_native/inc_openoffice/windows/msi_languages/LaunchCo.ulf4
-rw-r--r--instsetoo_native/inc_openoffice/windows/msi_templates/AppSearc.idt5
-rw-r--r--instsetoo_native/inc_openoffice/windows/msi_templates/Control.idt2
-rw-r--r--instsetoo_native/inc_openoffice/windows/msi_templates/CustomAc.idt1
-rw-r--r--instsetoo_native/inc_openoffice/windows/msi_templates/DrLocato.idt6
-rw-r--r--instsetoo_native/inc_openoffice/windows/msi_templates/InstallE.idt1
-rw-r--r--instsetoo_native/inc_openoffice/windows/msi_templates/InstallU.idt1
-rw-r--r--instsetoo_native/inc_openoffice/windows/msi_templates/LaunchCo.idt2
-rw-r--r--instsetoo_native/inc_openoffice/windows/msi_templates/RegLocat.idt2
-rw-r--r--instsetoo_native/inc_openoffice/windows/msi_templates/Signatur.idt13
-rw-r--r--instsetoo_native/inc_sdkoo/windows/msi_templates/Control.idt2
-rw-r--r--postprocess/signing/no_signing.txt8
-rw-r--r--scp2/InstallModule_windows.mk9
-rw-r--r--scp2/source/ooo/ucrt.scp154
-rw-r--r--scp2/source/ooo/vc_redist.scp27
-rw-r--r--setup_native/Library_inst_msu_msi.mk40
-rw-r--r--setup_native/Module_setup_native.mk1
-rw-r--r--setup_native/source/win32/customactions/inst_msu/inst_msu.cxx515
-rw-r--r--setup_native/source/win32/customactions/inst_msu/inst_msu_msi.def5
-rw-r--r--solenv/bin/modules/installer/windows/idtglobal.pm11
-rw-r--r--solenv/bin/modules/installer/windows/msiglobal.pm29
29 files changed, 827 insertions, 85 deletions
diff --git a/Repository.mk b/Repository.mk
index ec11fa4535a6..c75afa7b94a8 100644
--- a/Repository.mk
+++ b/Repository.mk
@@ -660,6 +660,7 @@ endif
$(eval $(call gb_Helper_register_libraries_for_install,PLAINLIBS_OOO,ooobinarytable, \
$(if $(WINDOWS_SDK_HOME),\
instooofiltmsi \
+ inst_msu_msi \
qslnkmsi \
reg4allmsdoc \
sdqsmsi \
diff --git a/RepositoryExternal.mk b/RepositoryExternal.mk
index c672632af80b..0efc07415413 100644
--- a/RepositoryExternal.mk
+++ b/RepositoryExternal.mk
@@ -4126,8 +4126,8 @@ $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,ooo,\
))
endif
-$(eval $(call gb_Helper_register_packages_for_install,vcredist_exe_binarytable,\
- $(if $(VCREDIST_DIR),vcredist_exe) \
+$(eval $(call gb_Helper_register_packages_for_install,ucrt_binarytable,\
+ $(if $(UCRT_REDISTDIR),ucrt) \
))
# vim: set noet sw=4 ts=4:
diff --git a/config_host.mk.in b/config_host.mk.in
index 8cbbc5fee1d5..b335cecb0cd7 100644
--- a/config_host.mk.in
+++ b/config_host.mk.in
@@ -582,8 +582,7 @@ export TMPDIR=@TEMP_DIRECTORY@
export TOUCH=@TOUCH@
export UCRTSDKDIR=@UCRTSDKDIR@
export UCRTVERSION=@UCRTVERSION@
-export VCREDIST_DIR=@VCREDIST_DIR@
-export VCREDIST_EXE=@VCREDIST_EXE@
+export UCRT_REDISTDIR=@UCRT_REDISTDIR@
export UNOWINREG_DLL=@UNOWINREG_DLL@
export USE_LIBRARY_BIN_TAR=@USE_LIBRARY_BIN_TAR@
export USE_XINERAMA=@USE_XINERAMA@
diff --git a/configure.ac b/configure.ac
index db52ee9456cc..7928b4705f39 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6486,13 +6486,21 @@ fi
AC_SUBST([JITC_PROCESSOR_TYPE])
# Misc Windows Stuff
-AC_ARG_WITH(vcredist-dir,
- AS_HELP_STRING([--with-vcredist-dir],
- [path to the directory with the arch-specific executables (vc_redist.x64.exe, vc_redist.x86.exe)
- for packaging into the installsets (without those the target system needs to install
- the Visual C++ Runtimes manually)]),
+AC_ARG_WITH(ucrt-dir,
+ AS_HELP_STRING([--with-ucrt-dir],
+ [path to the directory with the arch-specific MSU packages of the Windows Universal CRT redistributables
+ (MS KB 2999226) for packaging into the installsets (without those the target system needs to install
+ the UCRT or Visual C++ Runtimes manually). The directory must contain the following 6 files:
+ Windows6.1-KB2999226-x64.msu
+ Windows6.1-KB2999226-x86.msu
+ Windows8.1-KB2999226-x64.msu
+ Windows8.1-KB2999226-x86.msu
+ Windows8-RT-KB2999226-x64.msu
+ Windows8-RT-KB2999226-x86.msu
+ A zip archive including those files is available from Microsoft site:
+ https://www.microsoft.com/en-us/download/details.aspx?id=48234]),
,)
-VCREDIST_DIR="$with_vcredist_dir"
+UCRT_REDISTDIR="$with_ucrt_dir"
if test $_os = "WINNT"; then
find_msvc_x64_dlls
find_msms
@@ -6505,20 +6513,23 @@ if test $_os = "WINNT"; then
else
SCPDEFS="$SCPDEFS -DWITH_VC${VCVER}_REDIST"
fi
- if test "$VCREDIST_DIR" = "no"; then
+ if test "$UCRT_REDISTDIR" = "no"; then
dnl explicitly disabled
- VCREDIST_DIR=""
- else
- if test -f "$VCREDIST_DIR/vc_redist.$WINDOWS_SDK_ARCH.exe"; then
- VCREDIST_EXE="vc_redist.$WINDOWS_SDK_ARCH.exe"
- else
- VCREDIST_DIR=""
+ UCRT_REDISTDIR=""
+ else
+ if ! test -f "$UCRT_REDISTDIR/Windows6.1-KB2999226-x64.msu" -a \
+ -f "$UCRT_REDISTDIR/Windows6.1-KB2999226-x86.msu" -a \
+ -f "$UCRT_REDISTDIR/Windows8.1-KB2999226-x64.msu" -a \
+ -f "$UCRT_REDISTDIR/Windows8.1-KB2999226-x86.msu" -a \
+ -f "$UCRT_REDISTDIR/Windows8-RT-KB2999226-x64.msu" -a \
+ -f "$UCRT_REDISTDIR/Windows8-RT-KB2999226-x86.msu"; then
+ UCRT_REDISTDIR=""
if test -n "$PKGFORMAT"; then
for i in "$PKGFORMAT"; do
case "$i" in
msi)
- AC_MSG_WARN([--without-vcredist-dir not specified or exe not found - installer will have runtime dependency])
- add_warning "--without-vcredist-dir not specified or exe not found - installer will have runtime dependency"
+ AC_MSG_WARN([--without-ucrt-dir not specified or MSUs not found - installer will have runtime dependency])
+ add_warning "--without-ucrt-dir not specified or MSUs not found - installer will have runtime dependency"
;;
esac
done
@@ -6527,8 +6538,7 @@ if test $_os = "WINNT"; then
fi
fi
-AC_SUBST(VCREDIST_DIR)
-AC_SUBST(VCREDIST_EXE)
+AC_SUBST(UCRT_REDISTDIR)
AC_SUBST(MSVC_DLL_PATH)
AC_SUBST(MSVC_DLLS)
AC_SUBST(MSM_PATH)
diff --git a/external/msc-externals/Module_msc-externals.mk b/external/msc-externals/Module_msc-externals.mk
index b7f7f47034f9..07ea3878a106 100644
--- a/external/msc-externals/Module_msc-externals.mk
+++ b/external/msc-externals/Module_msc-externals.mk
@@ -17,11 +17,11 @@ $(eval $(call gb_Module_add_targets,msc-externals,\
endif
-# Install the universal crts and VC runtimes (tdf#108580)
-ifneq ($(VCREDIST_DIR),)
+# Install the universal crts (tdf#108580)
+ifneq ($(UCRT_REDISTDIR),)
$(eval $(call gb_Module_add_targets,msc-externals,\
- Package_vcredist_exe \
+ Package_ucrt \
))
endif
diff --git a/external/msc-externals/Package_vcredist_exe.mk b/external/msc-externals/Package_ucrt.mk
index bf9ef632285c..52e6f0cbae97 100644
--- a/external/msc-externals/Package_vcredist_exe.mk
+++ b/external/msc-externals/Package_ucrt.mk
@@ -7,10 +7,15 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
-$(eval $(call gb_Package_Package,vcredist_exe,$(VCREDIST_DIR)))
+$(eval $(call gb_Package_Package,ucrt,$(UCRT_REDISTDIR)))
-$(eval $(call gb_Package_add_files,vcredist_exe,$(LIBO_ETC_FOLDER),\
- $(VCREDIST_EXE) \
+$(eval $(call gb_Package_add_files,ucrt,$(LIBO_ETC_FOLDER),\
+ Windows6.1-KB2999226-x64.msu \
+ Windows6.1-KB2999226-x86.msu \
+ Windows8.1-KB2999226-x64.msu \
+ Windows8.1-KB2999226-x86.msu \
+ Windows8-RT-KB2999226-x64.msu \
+ Windows8-RT-KB2999226-x86.msu \
))
# vim:set shiftwidth=4 tabstop=4 noexpandtab:
diff --git a/instsetoo_native/inc_ooohelppack/windows/msi_templates/Control.idt b/instsetoo_native/inc_ooohelppack/windows/msi_templates/Control.idt
index 55f1fcfe6b20..24c02f85f7b8 100644
--- a/instsetoo_native/inc_ooohelppack/windows/msi_templates/Control.idt
+++ b/instsetoo_native/inc_ooohelppack/windows/msi_templates/Control.idt
@@ -249,7 +249,7 @@ SetupError I PushButton 192 80 66 17 3 OOO_CONTROL_207
SetupError N PushButton 192 80 66 17 3 OOO_CONTROL_208
SetupError O PushButton 192 80 66 17 3 OOO_CONTROL_209
SetupError R PushButton 192 80 66 17 3 OOO_CONTROL_210
-SetupError WarningIcon Icon 15 15 24 24 5242881 CautionIco
+SetupError ErrorIcon Icon 15 15 24 24 5242881 CautionIco
SetupError Y PushButton 192 80 66 17 3 OOO_CONTROL_211
SetupInitialization ActionData Text 135 125 228 12 65539
SetupInitialization ActionText Text 135 109 220 36 65539
diff --git a/instsetoo_native/inc_openoffice/windows/msi_languages/CustomAc.ulf b/instsetoo_native/inc_openoffice/windows/msi_languages/CustomAc.ulf
index 742cb8cbfb84..1038d6ca5679 100644
--- a/instsetoo_native/inc_openoffice/windows/msi_languages/CustomAc.ulf
+++ b/instsetoo_native/inc_openoffice/windows/msi_languages/CustomAc.ulf
@@ -21,6 +21,3 @@ en-US = "A newer version of [ProductName] was found. To install an older versio
[OOO_CUSTOMACTION_2]
en-US = "The same version of this product is already installed."
-
-[OOO_CUSTOMACTION_5]
-en-US = "[ProductName] cannot be installed on this Windows version. [WindowsMinVersionText] or newer is required."
diff --git a/instsetoo_native/inc_openoffice/windows/msi_languages/LaunchCo.ulf b/instsetoo_native/inc_openoffice/windows/msi_languages/LaunchCo.ulf
index e3f6f7fa8f53..5e57eb1c3c0e 100644
--- a/instsetoo_native/inc_openoffice/windows/msi_languages/LaunchCo.ulf
+++ b/instsetoo_native/inc_openoffice/windows/msi_languages/LaunchCo.ulf
@@ -1,2 +1,6 @@
[OOO_LAUNCH_1]
en-US = "The Installation Wizard cannot be run properly because you are logged in as a user without sufficient administrator rights for this system."
+[OOO_LAUNCH_2]
+en-US = "[ProductName] cannot be installed on this Windows version. [WindowsMinVersionText] or newer is required."
+[OOO_LAUNCH_3]
+en-US = "To install [ProductName] on Windows 8.1, at least April 2014 update rollup (MS KB 2919355) must be installed."
diff --git a/instsetoo_native/inc_openoffice/windows/msi_templates/AppSearc.idt b/instsetoo_native/inc_openoffice/windows/msi_templates/AppSearc.idt
index 095cf907bf46..23c2a77c9f5d 100644
--- a/instsetoo_native/inc_openoffice/windows/msi_templates/AppSearc.idt
+++ b/instsetoo_native/inc_openoffice/windows/msi_templates/AppSearc.idt
@@ -5,5 +5,6 @@ INSTALLLOCATION installuser
INSTALLLOCATION installuser_
INSTALLLOCATION installmachine
INSTALLLOCATION installmachine_
-VCREDISTINSTALLED_X86 VCREDISTINSTALLED_X86
-VCREDISTINSTALLED_X64 VCREDISTINSTALLED_X64
+WIN81S14 win81s14
+UCRT_DETECTED ucrt_detected
+UCRT_DETECTED ucrt_on_win10
diff --git a/instsetoo_native/inc_openoffice/windows/msi_templates/Control.idt b/instsetoo_native/inc_openoffice/windows/msi_templates/Control.idt
index f90d76f5717b..9871b7d3b8cd 100644
--- a/instsetoo_native/inc_openoffice/windows/msi_templates/Control.idt
+++ b/instsetoo_native/inc_openoffice/windows/msi_templates/Control.idt
@@ -253,7 +253,7 @@ SetupError I PushButton 192 80 66 17 3 OOO_CONTROL_207
SetupError N PushButton 192 80 66 17 3 OOO_CONTROL_208
SetupError O PushButton 192 80 66 17 3 OOO_CONTROL_209
SetupError R PushButton 192 80 66 17 3 OOO_CONTROL_210
-SetupError WarningIcon Icon 15 15 24 24 5242881 CautionIco
+SetupError ErrorIcon Icon 15 15 24 24 5242881 CautionIco
SetupError Y PushButton 192 80 66 17 3 OOO_CONTROL_211
SetupInitialization ActionData Text 135 125 228 12 65539
SetupInitialization ActionText Text 135 109 220 36 65539
diff --git a/instsetoo_native/inc_openoffice/windows/msi_templates/CustomAc.idt b/instsetoo_native/inc_openoffice/windows/msi_templates/CustomAc.idt
index 8aa06a155b46..d010a0bd2279 100644
--- a/instsetoo_native/inc_openoffice/windows/msi_templates/CustomAc.idt
+++ b/instsetoo_native/inc_openoffice/windows/msi_templates/CustomAc.idt
@@ -7,7 +7,6 @@ setUserProfile 51 USERPROFILE [%USERPROFILE]
SetARPInstallLocation 51 ARPINSTALLLOCATION [INSTALLLOCATION]
NewProductFound 19 OOO_CUSTOMACTION_1
SameProductFound 19 OOO_CUSTOMACTION_2
-WrongWindowsVersion 19 OOO_CUSTOMACTION_5
SetLanguageSelected 51 LANG_SELECTED 1
ResetLanguageSelected 51 LANG_SELECTED 0
SetApplicationSelected 51 APP_SELECTED 1
diff --git a/instsetoo_native/inc_openoffice/windows/msi_templates/DrLocato.idt b/instsetoo_native/inc_openoffice/windows/msi_templates/DrLocato.idt
new file mode 100644
index 000000000000..399011e166ca
--- /dev/null
+++ b/instsetoo_native/inc_openoffice/windows/msi_templates/DrLocato.idt
@@ -0,0 +1,6 @@
+Signature_ Parent Path Depth
+s72 S72 S255 I2
+DrLocator Signature_ Parent Path
+win81s14 [SystemFolder]
+ucrt_detected [SystemFolder]
+ucrt_on_win10 [SystemFolder]
diff --git a/instsetoo_native/inc_openoffice/windows/msi_templates/InstallE.idt b/instsetoo_native/inc_openoffice/windows/msi_templates/InstallE.idt
index 722bb463629d..336d322052e7 100644
--- a/instsetoo_native/inc_openoffice/windows/msi_templates/InstallE.idt
+++ b/instsetoo_native/inc_openoffice/windows/msi_templates/InstallE.idt
@@ -69,4 +69,3 @@ ValidateProductID 300
WriteEnvironmentStrings 2500
WriteIniValues 2450
WriteRegistryValues 2400
-WrongWindowsVersion (VersionNT < WindowsMinVersionNumber) OR ((VersionNT = WindowsMinVersionNumber) AND (ServicePackLevel < WindowsMinSPNumber)) 10
diff --git a/instsetoo_native/inc_openoffice/windows/msi_templates/InstallU.idt b/instsetoo_native/inc_openoffice/windows/msi_templates/InstallU.idt
index 3bb2a5191d20..642eac064bee 100644
--- a/instsetoo_native/inc_openoffice/windows/msi_templates/InstallU.idt
+++ b/instsetoo_native/inc_openoffice/windows/msi_templates/InstallU.idt
@@ -28,4 +28,3 @@ SetupProgress 800
SetupResume Installed And (RESUME Or Preselected) And Not PATCH 700
setUserProfile 510
ValidateProductID 350
-WrongWindowsVersion (VersionNT < WindowsMinVersionNumber) OR ((VersionNT = WindowsMinVersionNumber) AND (ServicePackLevel < WindowsMinSPNumber)) 10
diff --git a/instsetoo_native/inc_openoffice/windows/msi_templates/LaunchCo.idt b/instsetoo_native/inc_openoffice/windows/msi_templates/LaunchCo.idt
index e4d3f330b006..629c3c5582e1 100644
--- a/instsetoo_native/inc_openoffice/windows/msi_templates/LaunchCo.idt
+++ b/instsetoo_native/inc_openoffice/windows/msi_templates/LaunchCo.idt
@@ -2,3 +2,5 @@ Condition Description
s255 l255
65001 LaunchCondition Condition
Privileged OOO_LAUNCH_1
+Installed Or VersionNT > WindowsMinVersionNumber Or (VersionNT = WindowsMinVersionNumber And ServicePackLevel >= WindowsMinSPNumber) OOO_LAUNCH_2
+Installed Or VersionNT <> 603 Or WIN81S14 OOO_LAUNCH_3
diff --git a/instsetoo_native/inc_openoffice/windows/msi_templates/RegLocat.idt b/instsetoo_native/inc_openoffice/windows/msi_templates/RegLocat.idt
index 7e59ef3c6663..c082322086ad 100644
--- a/instsetoo_native/inc_openoffice/windows/msi_templates/RegLocat.idt
+++ b/instsetoo_native/inc_openoffice/windows/msi_templates/RegLocat.idt
@@ -5,5 +5,3 @@ installuser 1 Software\LibreOffice\Layers\[DEFINEDPRODUCT]\[BRANDPACKAGEVERSION]
installuser_ 1 Software\LibreOffice\Layers_\[DEFINEDPRODUCT]\[BRANDPACKAGEVERSION] INSTALLLOCATION 2
installmachine 2 Software\LibreOffice\Layers\[DEFINEDPRODUCT]\[BRANDPACKAGEVERSION] INSTALLLOCATION 2
installmachine_ 2 Software\LibreOffice\Layers_\[DEFINEDPRODUCT]\[BRANDPACKAGEVERSION] INSTALLLOCATION 2
-VCREDISTINSTALLED_X86 2 Software\Microsoft\VisualStudio\14.0\VC\Runtimes\x86 Version 2
-VCREDISTINSTALLED_X64 2 Software\Microsoft\VisualStudio\14.0\VC\Runtimes\x64 Version 2
diff --git a/instsetoo_native/inc_openoffice/windows/msi_templates/Signatur.idt b/instsetoo_native/inc_openoffice/windows/msi_templates/Signatur.idt
index 5004a55863ba..53615298dc6d 100644
--- a/instsetoo_native/inc_openoffice/windows/msi_templates/Signatur.idt
+++ b/instsetoo_native/inc_openoffice/windows/msi_templates/Signatur.idt
@@ -1,3 +1,16 @@
Signature FileName MinVersion MaxVersion MinSize MaxSize MinDate MaxDate Languages
s72 s255 S20 S20 I4 I4 I4 I4 S255
Signature Signature
+# Since it's impossible to match minimal version in Signature table independent of
+# language, and we need language-independent comparison, we use a value that is at
+# least 1 less (see note at https://msdn.microsoft.com/en-us/library/aa371853).
+win81s14 kernel32.dll 6.3.9600.17030
+ucrt_detected ucrtbase.dll 10.0.10240.0
+# The great feature of all recent Windows is that they make it incredibly hard to find their
+# actual versions. Win 10 makes the next step in that direction: not only it tells you that
+# its version is 6.3 (VersionNT is 603), but also it disallows you to get real version of a
+# file during installation, if the version is greater than 6.3. So, for ucrt DLLs versioned
+# by MS as 10.0.x.y, it returns 6.3.x.y, pretending to have a lower version than on Win8.1.
+# Here we check for this, knowing that we get a version below 7.0 for UCRT that never had a
+# version below 10.0, then it's Win10+ that is lying to us.
+ucrt_on_win10 ucrtbase.dll 7.0.0.0
diff --git a/instsetoo_native/inc_sdkoo/windows/msi_templates/Control.idt b/instsetoo_native/inc_sdkoo/windows/msi_templates/Control.idt
index 9bc37a8ed840..d9ac9d1a550a 100644
--- a/instsetoo_native/inc_sdkoo/windows/msi_templates/Control.idt
+++ b/instsetoo_native/inc_sdkoo/windows/msi_templates/Control.idt
@@ -236,7 +236,7 @@ SetupError I PushButton 192 80 66 17 3 OOO_CONTROL_207
SetupError N PushButton 192 80 66 17 3 OOO_CONTROL_208
SetupError O PushButton 192 80 66 17 3 OOO_CONTROL_209
SetupError R PushButton 192 80 66 17 3 OOO_CONTROL_210
-SetupError WarningIcon Icon 15 15 24 24 5242881 CautionIco
+SetupError ErrorIcon Icon 15 15 24 24 5242881 CautionIco
SetupError Y PushButton 192 80 66 17 3 OOO_CONTROL_211
SetupInitialization ActionData Text 135 125 228 12 65539
SetupInitialization ActionText Text 135 109 220 36 65539
diff --git a/postprocess/signing/no_signing.txt b/postprocess/signing/no_signing.txt
index 2fa129a80bab..6de68e2e8cc2 100644
--- a/postprocess/signing/no_signing.txt
+++ b/postprocess/signing/no_signing.txt
@@ -8,5 +8,9 @@ policy.1.0.cli_oootypes.dll
policy.1.0.cli_ure.dll
policy.1.0.cli_cppuhelper.dll
policy.1.0.cli_basetypes.dll
-vc_redist.x64.exe
-vc_redist.x86.exe
+Windows6.1-KB2999226-x64.msu
+Windows6.1-KB2999226-x86.msu
+Windows8.1-KB2999226-x64.msu
+Windows8.1-KB2999226-x86.msu
+Windows8-RT-KB2999226-x64.msu
+Windows8-RT-KB2999226-x86.msu
diff --git a/scp2/InstallModule_windows.mk b/scp2/InstallModule_windows.mk
index ecba37c42bca..bd6e478e7785 100644
--- a/scp2/InstallModule_windows.mk
+++ b/scp2/InstallModule_windows.mk
@@ -17,17 +17,12 @@ $(eval $(call gb_InstallModule_add_defs,scp2/windows,\
$(if $(WINDOWS_SDK_HOME),\
-DHAVE_WINDOWS_SDK \
) \
- $(if $(MSM_PATH),\
- -DMSM_PATH \
- ) \
- $(if $(VCREDIST_DIR),\
- -DVCREDIST_EXE_NAME="$(VCREDIST_EXE)" \
- ) \
))
$(eval $(call gb_InstallModule_add_scpfiles,scp2/windows,\
scp2/source/ooo/folder_ooo \
- scp2/source/ooo/vc_redist \
+ $(if $(MSM_PATH),scp2/source/ooo/vc_redist) \
+ $(if $(UCRT_REDISTDIR),scp2/source/ooo/ucrt) \
scp2/source/ooo/windowscustomaction_ooo \
))
diff --git a/scp2/source/ooo/ucrt.scp b/scp2/source/ooo/ucrt.scp
new file mode 100644
index 000000000000..4a13309f6364
--- /dev/null
+++ b/scp2/source/ooo/ucrt.scp
@@ -0,0 +1,154 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "macros.inc"
+
+File gid_File_Windows6_1_KB2999226_x64_msu
+ Name = "Windows6.1-KB2999226-x64.msu";
+ Dir = gid_Brand_Dir_Program;
+ Styles = (PACKED, BINARYTABLE, BINARYTABLE_ONLY);
+End
+
+File gid_File_Windows8_RT_KB2999226_x64_msu
+ Name = "Windows8-RT-KB2999226-x64.msu";
+ Dir = gid_Brand_Dir_Program;
+ Styles = (PACKED, BINARYTABLE, BINARYTABLE_ONLY);
+End
+
+File gid_File_Windows8_1_KB2999226_x64_msu
+ Name = "Windows8.1-KB2999226-x64.msu";
+ Dir = gid_Brand_Dir_Program;
+ Styles = (PACKED, BINARYTABLE, BINARYTABLE_ONLY);
+End
+
+#ifndef WINDOWS_X64
+
+File gid_File_Windows6_1_KB2999226_x86_msu
+ Name = "Windows6.1-KB2999226-x86.msu";
+ Dir = gid_Brand_Dir_Program;
+ Styles = (PACKED, BINARYTABLE, BINARYTABLE_ONLY);
+End
+
+File gid_File_Windows8_RT_KB2999226_x86_msu
+ Name = "Windows8-RT-KB2999226-x86.msu";
+ Dir = gid_Brand_Dir_Program;
+ Styles = (PACKED, BINARYTABLE, BINARYTABLE_ONLY);
+End
+
+File gid_File_Windows8_1_KB2999226_x86_msu
+ Name = "Windows8.1-KB2999226-x86.msu";
+ Dir = gid_Brand_Dir_Program;
+ Styles = (PACKED, BINARYTABLE, BINARYTABLE_ONLY);
+End
+
+#endif /* WINDOWS_X64 */
+
+/* A deferred not-impersonated action that will call wusa.exe to actually install
+ msu. Since deferred actions don't have access to current DB, the action depends
+ on immediate-executed action inst_ucrt (see below) that precedes it, unpacks
+ the binary to a temp file, and sets this action's CustomActionData property.
+*/
+WindowsCustomAction gid_Customaction_inst_msu
+ Name = "inst_msu";
+ Typ = "3073";
+ Source = "inst_msu_msi.dll";
+ Target = "InstallMSU";
+ Inbinarytable = 1;
+ Assignment1 = ("InstallExecuteSequence", "Not Installed And inst_msu", "InstallFiles");
+End
+
+/* An immediately-executed action that will unpack a binary, which name in binary table is set
+ in "InstMSUBinary" property, to a temporary file, and sets "inst_msu" and "cleanup_msu" props.
+*/
+WindowsCustomAction gid_Customaction_unpack_msu
+ Name = "unpack_msu";
+ Typ = "1";
+ Source = "inst_msu_msi.dll";
+ Target = "UnpackMSUForInstall";
+ Inbinarytable = 1;
+ Assignment1 = ("InstallExecuteSequence", "Not Installed And InstMSUBinary", "cleanup_msu");
+End
+
+/* A rollback action that removes temp file. It must precede inst_msu.
+*/
+WindowsCustomAction gid_Customaction_cleanup_msu
+ Name = "cleanup_msu";
+ Typ = "1345";
+ Source = "inst_msu_msi.dll";
+ Target = "CleanupMSU";
+ Inbinarytable = 1;
+ Assignment1 = ("InstallExecuteSequence", "Not Installed And cleanup_msu", "inst_msu");
+End
+
+WindowsCustomAction gid_Customaction_check_win7x64_ucrt
+ Name = "check_win7x64_ucrt";
+ Typ = "51";
+ Source = "InstMSUBinary";
+ Target = "Windows61-KB2999226-x64msu";
+ Inbinarytable = 0;
+ Assignment1 = ("InstallExecuteSequence", "Not Installed And VersionNT = 601 And VersionNT64 And Not UCRT_DETECTED", "FileCost");
+ Styles = "NO_FILE";
+End
+
+WindowsCustomAction gid_Customaction_check_win8x64_ucrt
+ Name = "check_win8x64_ucrt";
+ Typ = "51";
+ Source = "InstMSUBinary";
+ Target = "Windows8-RT-KB2999226-x64msu";
+ Inbinarytable = 0;
+ Assignment1 = ("InstallExecuteSequence", "Not Installed And VersionNT = 602 And VersionNT64 And Not UCRT_DETECTED", "check_win7x64_ucrt");
+ Styles = "NO_FILE";
+End
+
+WindowsCustomAction gid_Customaction_check_win81x64_ucrt
+ Name = "check_win81x64_ucrt";
+ Typ = "51";
+ Source = "InstMSUBinary";
+ Target = "Windows81-KB2999226-x64msu";
+ Inbinarytable = 0;
+ Assignment1 = ("InstallExecuteSequence", "Not Installed And VersionNT = 603 And VersionNT64 And Not UCRT_DETECTED", "check_win8x64_ucrt");
+ Styles = "NO_FILE";
+End
+
+#ifndef WINDOWS_X64
+
+/* 32-bit installer must be prepared to run on both 32- and 64-bit Windows. So, it might need to
+ install either 32-bit or 64-bit UCRT package, depending on OS bitness.
+*/
+
+WindowsCustomAction gid_Customaction_check_win7x32_ucrt
+ Name = "check_win7x32_ucrt";
+ Typ = "51";
+ Source = "InstMSUBinary";
+ Target = "Windows61-KB2999226-x86msu";
+ Inbinarytable = 0;
+ Assignment1 = ("InstallExecuteSequence", "Not Installed And VersionNT = 601 And Not VersionNT64 And Not UCRT_DETECTED", "check_win81x64_ucrt");
+ Styles = "NO_FILE";
+End
+
+WindowsCustomAction gid_Customaction_check_win8x32_ucrt
+ Name = "check_win8x32_ucrt";
+ Typ = "51";
+ Source = "InstMSUBinary";
+ Target = "Windows8-RT-KB2999226-x86msu";
+ Inbinarytable = 0;
+ Assignment1 = ("InstallExecuteSequence", "Not Installed And VersionNT = 602 And Not VersionNT64 And Not UCRT_DETECTED", "check_win7x32_ucrt");
+ Styles = "NO_FILE";
+End
+
+WindowsCustomAction gid_Customaction_check_win81x32_ucrt
+ Name = "check_win81x32_ucrt";
+ Typ = "51";
+ Source = "InstMSUBinary";
+ Target = "Windows81-KB2999226-x86msu";
+ Inbinarytable = 0;
+ Assignment1 = ("InstallExecuteSequence", "Not Installed And VersionNT = 603 And Not VersionNT64 And Not UCRT_DETECTED", "check_win8x32_ucrt");
+ Styles = "NO_FILE";
+End
+
+#endif /* WINDOWS_X64 */
diff --git a/scp2/source/ooo/vc_redist.scp b/scp2/source/ooo/vc_redist.scp
index 9b414b8e39fa..727c13b27615 100644
--- a/scp2/source/ooo/vc_redist.scp
+++ b/scp2/source/ooo/vc_redist.scp
@@ -18,8 +18,6 @@
#include "macros.inc"
-#if defined(MSM_PATH)
-
#if defined(WITH_VC140_REDIST)
#if defined WINDOWS_X64
@@ -76,28 +74,3 @@ MergeModule gid_MergeModule_Microsoft_VC141_CRT_x86
End
#endif
-
-#endif // MSM_PATH
-
-#if defined(VCREDIST_EXE_NAME)
-
-File gid_File_Vcredist_Exe
- Name = VCREDIST_EXE_NAME;
- Dir = gid_Brand_Dir_Program;
- Styles = (PACKED, BINARYTABLE, BINARYTABLE_ONLY);
-End
-
-WindowsCustomAction gid_Customaction_InstallVCRedist
- Name = "InstallVCRedist";
- Typ = "66"; /* 0x02 = exe in a binary table stream; 0x40 = ignore exit code and continue */
- Source = VCREDIST_EXE_NAME;
- Target = "/repair /norestart /passive";
- Inbinarytable = 1;
-#if defined WINDOWS_X64
- Assignment1 = ("InstallUISequence", "Not Installed And ( Not VCREDISTINSTALLED_X64 Or VCREDISTINSTALLED_X64 < \"v14.0.24215.0\" )", "behind_ExecuteAction");
-#else
- Assignment1 = ("InstallUISequence", "Not Installed And ( Not VCREDISTINSTALLED_X86 Or VCREDISTINSTALLED_X86 < \"v14.0.24215.0\" )", "behind_ExecuteAction");
-#endif
-End
-
-#endif
diff --git a/setup_native/Library_inst_msu_msi.mk b/setup_native/Library_inst_msu_msi.mk
new file mode 100644
index 000000000000..d423b5168697
--- /dev/null
+++ b/setup_native/Library_inst_msu_msi.mk
@@ -0,0 +1,40 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Library_Library,inst_msu_msi))
+
+$(eval $(call gb_Library_add_defs,inst_msu_msi,\
+ -U_DLL \
+))
+
+$(eval $(call gb_Library_add_cxxflags,inst_msu_msi,\
+ $(if $(MSVC_USE_DEBUG_RUNTIME),/MTd,/MT) \
+))
+
+$(eval $(call gb_Library_add_ldflags,inst_msu_msi,\
+ /DEF:$(SRCDIR)/setup_native/source/win32/customactions/inst_msu/inst_msu_msi.def \
+ /NODEFAULTLIB \
+))
+
+$(eval $(call gb_Library_add_exception_objects,inst_msu_msi,\
+ setup_native/source/win32/customactions/inst_msu/inst_msu \
+))
+
+$(eval $(call gb_Library_use_system_win32_libs,inst_msu_msi,\
+ libcmt \
+ libcpmt \
+ libucrt \
+ libvcruntime \
+ kernel32 \
+ Ole32 \
+ Shell32 \
+ Msi \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/setup_native/Module_setup_native.mk b/setup_native/Module_setup_native.mk
index 43d1adb181ff..abf37aff6c86 100644
--- a/setup_native/Module_setup_native.mk
+++ b/setup_native/Module_setup_native.mk
@@ -24,6 +24,7 @@ $(eval $(call gb_Module_add_targets,setup_native,\
ifeq ($(OS),WNT)
$(eval $(call gb_Module_add_targets,setup_native,\
Library_instooofiltmsi \
+ Library_inst_msu_msi \
Library_qslnkmsi \
Library_reg4allmsdoc \
Library_regactivex \
diff --git a/setup_native/source/win32/customactions/inst_msu/inst_msu.cxx b/setup_native/source/win32/customactions/inst_msu/inst_msu.cxx
new file mode 100644
index 000000000000..b03d3cf3791c
--- /dev/null
+++ b/setup_native/source/win32/customactions/inst_msu/inst_msu.cxx
@@ -0,0 +1,515 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <memory>
+#include <string>
+#include <sstream>
+#include <iomanip>
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <Shlobj.h>
+#include <Wuerror.h>
+#include <msiquery.h>
+
+namespace
+{
+template <typename IntType> std::string Num2Hex(IntType n)
+{
+ std::stringstream sMsg;
+ sMsg << "0x" << std::uppercase << std::setfill('0') << std::setw(sizeof(n) * 2) << std::hex
+ << n;
+ return sMsg.str();
+}
+
+template <typename IntType> std::string Num2Dec(IntType n)
+{
+ std::stringstream sMsg;
+ sMsg << n;
+ return sMsg.str();
+}
+
+void ThrowHResult(const char* sFunc, HRESULT hr)
+{
+ std::stringstream sMsg;
+ sMsg << sFunc << " failed (HRESULT = " << Num2Hex(hr) << ")!";
+
+ throw std::exception(sMsg.str().c_str());
+}
+
+void CheckHResult(const char* sFunc, HRESULT hr)
+{
+ if (FAILED(hr))
+ ThrowHResult(sFunc, hr);
+}
+
+void ThrowWin32Error(const char* sFunc, DWORD nWin32Error)
+{
+ std::stringstream sMsg;
+ sMsg << sFunc << " failed with Win32 error code " << Num2Hex(nWin32Error) << "!";
+
+ throw std::exception(sMsg.str().c_str());
+}
+
+void ThrowLastError(const char* sFunc) { ThrowWin32Error(sFunc, GetLastError()); }
+
+void CheckWin32Error(const char* sFunc, DWORD nWin32Error)
+{
+ if (nWin32Error != ERROR_SUCCESS)
+ ThrowWin32Error(sFunc, nWin32Error);
+}
+
+std::wstring GetKnownFolder(const KNOWNFOLDERID& rfid)
+{
+ PWSTR sPath = nullptr;
+ HRESULT hr = SHGetKnownFolderPath(rfid, KF_FLAG_DEFAULT, nullptr, &sPath);
+ CheckHResult("SHGetKnownFolderPath", hr);
+ std::wstring sResult(sPath);
+ CoTaskMemFree(sPath);
+ return sResult;
+}
+
+void WriteLogElem(MSIHANDLE hInst, MSIHANDLE hRecord, std::ostringstream& sTmpl, UINT)
+{
+ MsiRecordSetStringA(hRecord, 0, sTmpl.str().c_str());
+ MsiProcessMessage(hInst, INSTALLMESSAGE_INFO, hRecord);
+}
+
+void RecSetString(MSIHANDLE hRec, UINT nField, LPCSTR sVal)
+{
+ MsiRecordSetStringA(hRec, nField, sVal);
+}
+
+void RecSetString(MSIHANDLE hRec, UINT nField, LPCWSTR sVal)
+{
+ MsiRecordSetStringW(hRec, nField, sVal);
+}
+
+template <class Ch, class... SOther>
+void WriteLogElem(MSIHANDLE hInst, MSIHANDLE hRec, std::ostringstream& sTmpl, UINT nField,
+ const Ch* elem, const SOther&... others)
+{
+ sTmpl << " [" << nField << "]";
+ RecSetString(hRec, nField, elem);
+ WriteLogElem(hInst, hRec, sTmpl, nField + 1, others...);
+}
+
+template <class S1, class... SOther>
+void WriteLogElem(MSIHANDLE hInst, MSIHANDLE hRec, std::ostringstream& sTmpl, UINT nField,
+ const S1& elem, const SOther&... others)
+{
+ WriteLogElem(hInst, hRec, sTmpl, nField, elem.c_str(), others...);
+}
+
+static std::string sLogPrefix;
+
+template <class... StrType> void WriteLog(MSIHANDLE hInst, const StrType&... elements)
+{
+ PMSIHANDLE hRec = MsiCreateRecord(sizeof...(elements));
+ if (!hRec)
+ return;
+
+ std::ostringstream sTemplate;
+ sTemplate << sLogPrefix;
+ WriteLogElem(hInst, hRec, sTemplate, 1, elements...);
+}
+
+typedef std::unique_ptr<void, decltype(&CloseHandle)> CloseHandleGuard;
+CloseHandleGuard Guard(HANDLE h) { return CloseHandleGuard(h, CloseHandle); }
+
+typedef std::unique_ptr<const wchar_t, decltype(&DeleteFileW)> DeleteFileGuard;
+DeleteFileGuard Guard(const wchar_t* sFileName) { return DeleteFileGuard(sFileName, DeleteFileW); }
+
+typedef std::unique_ptr<SC_HANDLE__, decltype(&CloseServiceHandle)> CloseServiceHandleGuard;
+CloseServiceHandleGuard Guard(SC_HANDLE h)
+{
+ return CloseServiceHandleGuard(h, CloseServiceHandle);
+}
+
+std::wstring GetTempFile()
+{
+ wchar_t sPath[MAX_PATH + 1];
+ DWORD nResult = GetTempPathW(sizeof(sPath) / sizeof(*sPath), sPath);
+ if (!nResult)
+ ThrowLastError("GetTempPathW");
+
+ wchar_t sFile[MAX_PATH + 1];
+ nResult = GetTempFileNameW(sPath, L"TMP", 0, sFile);
+ if (!nResult)
+ ThrowLastError("GetTempFileNameW");
+ return sFile;
+}
+
+bool IsWow64Process()
+{
+#if !defined _WIN64
+ BOOL bResult = FALSE;
+ typedef BOOL(WINAPI * LPFN_ISWOW64PROCESS)(HANDLE, PBOOL);
+ LPFN_ISWOW64PROCESS fnIsWow64Process = reinterpret_cast<LPFN_ISWOW64PROCESS>(
+ GetProcAddress(GetModuleHandleW(L"kernel32"), "IsWow64Process"));
+
+ if (fnIsWow64Process)
+ {
+ if (!fnIsWow64Process(GetCurrentProcess(), &bResult))
+ ThrowLastError("IsWow64Process");
+ }
+
+ return bResult;
+#else
+ return false;
+#endif
+}
+
+// Checks if Windows Update service is disabled, and if it is, enables it temporarily.
+class WUServiceEnabler
+{
+public:
+ WUServiceEnabler(MSIHANDLE hInstall)
+ : mhInstall(hInstall)
+ , mhService(EnableWUService(hInstall))
+ {
+ }
+
+ ~WUServiceEnabler()
+ {
+ try
+ {
+ if (mhService)
+ {
+ EnsureServiceEnabled(mhInstall, mhService.get(), false);
+ StopService(mhInstall, mhService.get());
+ }
+ }
+ catch (std::exception& e)
+ {
+ WriteLog(mhInstall, e.what());
+ }
+ }
+
+private:
+ static CloseServiceHandleGuard EnableWUService(MSIHANDLE hInstall)
+ {
+ auto hSCM = Guard(OpenSCManagerW(nullptr, nullptr, SC_MANAGER_ALL_ACCESS));
+ if (!hSCM)
+ ThrowLastError("OpenSCManagerW");
+ WriteLog(hInstall, "Opened service control manager");
+
+ auto hService = Guard(OpenServiceW(hSCM.get(), L"wuauserv",
+ SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG
+ | SERVICE_QUERY_STATUS | SERVICE_STOP));
+ if (!hService)
+ ThrowLastError("OpenServiceW");
+ WriteLog(hInstall, "Obtained WU service handle");
+
+ if (ServiceStatus(hInstall, hService.get()) == SERVICE_RUNNING
+ || !EnsureServiceEnabled(hInstall, hService.get(), true))
+ {
+ // No need to restore anything back, since we didn't change config
+ hService.reset();
+ WriteLog(hInstall, "Service configuration is unchanged");
+ }
+
+ return hService;
+ }
+
+ // Returns if the service configuration was actually changed
+ static bool EnsureServiceEnabled(MSIHANDLE hInstall, SC_HANDLE hService, bool bEnabled)
+ {
+ bool bConfigChanged = false;
+
+ DWORD nCbRequired = 0;
+ if (!QueryServiceConfigW(hService, nullptr, 0, &nCbRequired))
+ {
+ DWORD nError = GetLastError();
+ if (nError != ERROR_INSUFFICIENT_BUFFER)
+ ThrowLastError("QueryServiceConfigW");
+ }
+ std::unique_ptr<char[]> pBuf(new char[nCbRequired]);
+ LPQUERY_SERVICE_CONFIGW pConfig = reinterpret_cast<LPQUERY_SERVICE_CONFIGW>(pBuf.get());
+ if (!QueryServiceConfigW(hService, pConfig, nCbRequired, &nCbRequired))
+ ThrowLastError("QueryServiceConfigW");
+ WriteLog(hInstall, "Obtained service config");
+
+ DWORD eNewStartType = 0;
+ if (bEnabled && pConfig->dwStartType == SERVICE_DISABLED)
+ {
+ bConfigChanged = true;
+ eNewStartType = SERVICE_DEMAND_START;
+ WriteLog(hInstall, "Service is disabled, and requested to enable");
+ }
+ else if (!bEnabled && pConfig->dwStartType != SERVICE_DISABLED)
+ {
+ bConfigChanged = true;
+ eNewStartType = SERVICE_DISABLED;
+ WriteLog(hInstall, "Service is enabled, and requested to disable");
+ }
+
+ if (bConfigChanged)
+ {
+ if (!ChangeServiceConfigW(hService, SERVICE_NO_CHANGE, eNewStartType, SERVICE_NO_CHANGE,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr))
+ ThrowLastError("ChangeServiceConfigW");
+ WriteLog(hInstall, "WU service config successfully changed");
+ }
+ else
+ WriteLog(hInstall, "No need to modify service config");
+
+ return bConfigChanged;
+ }
+
+ static DWORD ServiceStatus(MSIHANDLE hInstall, SC_HANDLE hService)
+ {
+ SERVICE_STATUS aServiceStatus{};
+ if (!QueryServiceStatus(hService, &aServiceStatus))
+ ThrowLastError("QueryServiceStatus");
+
+ std::string sStatus;
+ switch (aServiceStatus.dwCurrentState)
+ {
+ case SERVICE_STOPPED:
+ sStatus = "SERVICE_STOPPED";
+ break;
+ case SERVICE_START_PENDING:
+ sStatus = "SERVICE_START_PENDING";
+ break;
+ case SERVICE_STOP_PENDING:
+ sStatus = "SERVICE_STOP_PENDING";
+ break;
+ case SERVICE_RUNNING:
+ sStatus = "SERVICE_RUNNING";
+ break;
+ case SERVICE_CONTINUE_PENDING:
+ sStatus = "SERVICE_CONTINUE_PENDING";
+ break;
+ case SERVICE_PAUSE_PENDING:
+ sStatus = "SERVICE_PAUSE_PENDING";
+ break;
+ case SERVICE_PAUSED:
+ sStatus = "SERVICE_PAUSED";
+ break;
+ default:
+ sStatus = Num2Hex(aServiceStatus.dwCurrentState);
+ }
+ WriteLog(hInstall, "Service status is", sStatus);
+
+ return aServiceStatus.dwCurrentState;
+ }
+
+ static void StopService(MSIHANDLE hInstall, SC_HANDLE hService)
+ {
+ if (ServiceStatus(hInstall, hService) != SERVICE_STOPPED)
+ {
+ SERVICE_STATUS aServiceStatus{};
+ if (!ControlService(hService, SERVICE_CONTROL_STOP, &aServiceStatus))
+ ThrowLastError("ControlService");
+ WriteLog(hInstall,
+ "Successfully sent SERVICE_CONTROL_STOP code to Windows Update service");
+ // No need to wait for the service stopped
+ }
+ else
+ WriteLog(hInstall, "Windows Update service is not running");
+ }
+
+ MSIHANDLE mhInstall;
+ CloseServiceHandleGuard mhService;
+};
+}
+
+// Immediate action "unpack_msu" that has access to installation database and properties; checks
+// "InstMSUBinary" property and unpacks the binary with that name to a temporary file; sets
+// "cleanup_msu" and "inst_msu" properties to the full name of the extracted temporary file. These
+// properties will become "CustomActionData" property inside relevant deferred actions.
+extern "C" UINT __stdcall UnpackMSUForInstall(MSIHANDLE hInstall)
+{
+ try
+ {
+ sLogPrefix = "UnpackMSUForInstall:";
+ WriteLog(hInstall, "started");
+
+ WriteLog(hInstall, "Checking value of InstMSUBinary");
+ wchar_t sBinaryName[MAX_PATH + 1];
+ DWORD nCCh = sizeof(sBinaryName) / sizeof(*sBinaryName);
+ CheckWin32Error("MsiGetPropertyW",
+ MsiGetPropertyW(hInstall, L"InstMSUBinary", sBinaryName, &nCCh));
+ WriteLog(hInstall, "Got InstMSUBinary value:", sBinaryName);
+
+ PMSIHANDLE hDatabase = MsiGetActiveDatabase(hInstall);
+ if (!hDatabase)
+ ThrowLastError("MsiGetActiveDatabase");
+ WriteLog(hInstall, "MsiGetActiveDatabase succeeded");
+
+ std::wstringstream sQuery;
+ sQuery << "SELECT `Data` FROM `Binary` WHERE `Name`='" << sBinaryName << "'";
+
+ PMSIHANDLE hBinaryView;
+ CheckWin32Error("MsiDatabaseOpenViewW",
+ MsiDatabaseOpenViewW(hDatabase, sQuery.str().c_str(), &hBinaryView));
+ WriteLog(hInstall, "MsiDatabaseOpenViewW succeeded");
+
+ CheckWin32Error("MsiViewExecute", MsiViewExecute(hBinaryView, 0));
+ WriteLog(hInstall, "MsiViewExecute succeeded");
+
+ PMSIHANDLE hBinaryRecord;
+ CheckWin32Error("MsiViewFetch", MsiViewFetch(hBinaryView, &hBinaryRecord));
+ WriteLog(hInstall, "MsiViewFetch succeeded");
+
+ const std::wstring sBinary = GetTempFile();
+ auto aDeleteFileGuard(Guard(sBinary.c_str()));
+ WriteLog(hInstall, "Temp file path:", sBinary.c_str());
+
+ CheckWin32Error("MsiSetPropertyW",
+ MsiSetPropertyW(hInstall, L"cleanup_msu", sBinary.c_str()));
+
+ {
+ HANDLE hFile = CreateFileW(sBinary.c_str(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, 0);
+ if (hFile == INVALID_HANDLE_VALUE)
+ ThrowLastError("CreateFileW");
+ auto aFileHandleGuard(Guard(hFile));
+
+ const DWORD nBufSize = 1024 * 1024;
+ std::unique_ptr<char[]> buf(new char[nBufSize]);
+ DWORD nTotal = 0;
+ DWORD nRead;
+ do
+ {
+ nRead = nBufSize;
+ CheckWin32Error("MsiRecordReadStream",
+ MsiRecordReadStream(hBinaryRecord, 1, buf.get(), &nRead));
+
+ if (nRead > 0)
+ {
+ DWORD nWritten;
+ if (!WriteFile(hFile, buf.get(), nRead, &nWritten, nullptr))
+ ThrowLastError("WriteFile");
+ nTotal += nWritten;
+ }
+ } while (nRead == nBufSize);
+
+ WriteLog(hInstall, "Successfully wrote", Num2Dec(nTotal), "bytes");
+ }
+
+ CheckWin32Error("MsiSetPropertyW", MsiSetPropertyW(hInstall, L"inst_msu", sBinary.c_str()));
+
+ // Don't delete the file: it will be done by following actions (inst_msu or cleanup_msu)
+ aDeleteFileGuard.release();
+ return ERROR_SUCCESS;
+ }
+ catch (std::exception& e)
+ {
+ WriteLog(hInstall, e.what());
+ }
+ return ERROR_INSTALL_FAILURE;
+}
+
+// Deferred action "inst_msu" that must be run from system account. Receives the tempfile name from
+// "CustomActionData" property, and runs wusa.exe to install it. Waits for it and checks exit code.
+extern "C" UINT __stdcall InstallMSU(MSIHANDLE hInstall)
+{
+ try
+ {
+ sLogPrefix = "InstallMSU:";
+ WriteLog(hInstall, "started");
+
+ WriteLog(hInstall, "Checking value of CustomActionData");
+ wchar_t sBinaryName[MAX_PATH + 1];
+ DWORD nCCh = sizeof(sBinaryName) / sizeof(*sBinaryName);
+ CheckWin32Error("MsiGetPropertyW",
+ MsiGetPropertyW(hInstall, L"CustomActionData", sBinaryName, &nCCh));
+ WriteLog(hInstall, "Got CustomActionData value:", sBinaryName);
+ auto aDeleteFileGuard(Guard(sBinaryName));
+
+ // In case the Windows Update service is disabled, we temporarily enable it here
+ WUServiceEnabler aWUServiceEnabler(hInstall);
+
+ const bool bWow64Process = IsWow64Process();
+ WriteLog(hInstall, "Is Wow64 Process:", bWow64Process ? "YES" : "NO");
+ std::wstring sWUSAPath = bWow64Process ? GetKnownFolder(FOLDERID_Windows) + L"\\SysNative"
+ : GetKnownFolder(FOLDERID_System);
+ sWUSAPath += L"\\wusa.exe";
+ WriteLog(hInstall, "Prepared wusa path:", sWUSAPath);
+
+ std::wstring sWUSACmd
+ = L"\"" + sWUSAPath + L"\" \"" + sBinaryName + L"\" /quiet /norestart";
+ WriteLog(hInstall, "Prepared wusa command:", sWUSACmd);
+
+ STARTUPINFOW si{};
+ si.cb = sizeof(si);
+ PROCESS_INFORMATION pi{};
+ if (!CreateProcessW(sWUSAPath.c_str(), const_cast<LPWSTR>(sWUSACmd.c_str()), nullptr,
+ nullptr, FALSE, CREATE_NO_WINDOW, nullptr, nullptr, &si, &pi))
+ ThrowLastError("CreateProcessW");
+ auto aCloseProcHandleGuard(Guard(pi.hProcess));
+ WriteLog(hInstall, "CreateProcessW succeeded");
+
+ DWORD nWaitResult = WaitForSingleObject(pi.hProcess, INFINITE);
+ if (nWaitResult != WAIT_OBJECT_0)
+ ThrowWin32Error("WaitForSingleObject", nWaitResult);
+
+ DWORD nExitCode = 0;
+ if (!GetExitCodeProcess(pi.hProcess, &nExitCode))
+ ThrowLastError("GetExitCodeProcess");
+
+ HRESULT hr = static_cast<HRESULT>(nExitCode);
+ if (hr == HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED))
+ hr = WU_S_REBOOT_REQUIRED;
+
+ switch (hr)
+ {
+ case S_OK:
+ case S_FALSE:
+ case WU_S_ALREADY_INSTALLED:
+ case WU_E_NOT_APPLICABLE: // Windows could lie us about its version, etc.
+ case ERROR_SUCCESS_REBOOT_REQUIRED:
+ case WU_S_REBOOT_REQUIRED:
+ WriteLog(hInstall, "wusa.exe succeeded with exit code", Num2Hex(nExitCode));
+ return ERROR_SUCCESS;
+
+ default:
+ ThrowWin32Error("Execution of wusa.exe", nExitCode);
+ }
+ }
+ catch (std::exception& e)
+ {
+ WriteLog(hInstall, e.what());
+ }
+ return ERROR_INSTALL_FAILURE;
+}
+
+// Rollback deferred action "cleanup_msu" that is executed on error or cancel.
+// It removes the temporary file created by UnpackMSUForInstall action.
+// MUST be placed IMMEDIATELY AFTER "unpack_msu" in execute sequence.
+extern "C" UINT __stdcall CleanupMSU(MSIHANDLE hInstall)
+{
+ try
+ {
+ sLogPrefix = "CleanupMSU:";
+ WriteLog(hInstall, "started");
+
+ WriteLog(hInstall, "Checking value of CustomActionData");
+ wchar_t sBinaryName[MAX_PATH + 1];
+ DWORD nCCh = sizeof(sBinaryName) / sizeof(*sBinaryName);
+ CheckWin32Error("MsiGetPropertyW",
+ MsiGetPropertyW(hInstall, L"CustomActionData", sBinaryName, &nCCh));
+ WriteLog(hInstall, "Got CustomActionData value:", sBinaryName);
+
+ if (!DeleteFileW(sBinaryName))
+ ThrowLastError("DeleteFileW");
+ WriteLog(hInstall, "File successfully removed");
+ }
+ catch (std::exception& e)
+ {
+ WriteLog(hInstall, e.what());
+ }
+ // Always return success - we don't want rollback to fail.
+ return ERROR_SUCCESS;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/setup_native/source/win32/customactions/inst_msu/inst_msu_msi.def b/setup_native/source/win32/customactions/inst_msu/inst_msu_msi.def
new file mode 100644
index 000000000000..49ade9c0169e
--- /dev/null
+++ b/setup_native/source/win32/customactions/inst_msu/inst_msu_msi.def
@@ -0,0 +1,5 @@
+LIBRARY "inst_msu_msi.dll"
+EXPORTS
+ UnpackMSUForInstall
+ InstallMSU
+ CleanupMSU \ No newline at end of file
diff --git a/solenv/bin/modules/installer/windows/idtglobal.pm b/solenv/bin/modules/installer/windows/idtglobal.pm
index 8e81a0469717..a98b4acb619e 100644
--- a/solenv/bin/modules/installer/windows/idtglobal.pm
+++ b/solenv/bin/modules/installer/windows/idtglobal.pm
@@ -1084,9 +1084,8 @@ sub add_custom_action_to_install_table
my $actionposition = 0;
- if ( $position eq "end" ) { $actionposition = get_last_position_in_sequencetable($installtable) + 25; }
- elsif ( $position =~ /^\s*behind_/ ) { $actionposition = get_position_in_sequencetable($position, $installtable) + 2; }
- else { $actionposition = get_position_in_sequencetable($position, $installtable) - 2; }
+ if ( $position =~ /^\s*\d+\s*$/ ) { $actionposition = $position; } # setting the position directly, number defined in scp2
+ else { $actionposition = "POSITIONTEMPLATE_" . $position; }
my $line = $actionname . "\t" . $actioncondition . "\t" . $actionposition . "\n";
push(@{$installtable}, $line);
@@ -1129,12 +1128,6 @@ sub add_custom_action_to_install_table
$actioncondition =~ s/FEATURETEMPLATE/$feature/g; # only execute Custom Action, if feature of the file is installed
-# my $actionposition = 0;
-# if ( $position eq "end" ) { $actionposition = get_last_position_in_sequencetable($installtable) + 25; }
-# elsif ( $position =~ /^\s*behind_/ ) { $actionposition = get_position_in_sequencetable($position, $installtable) + 2; }
-# else { $actionposition = get_position_in_sequencetable($position, $installtable) - 2; }
-# my $line = $actionname . "\t" . $actioncondition . "\t" . $actionposition . "\n";
-
my $positiontemplate = "";
if ( $position =~ /^\s*\d+\s*$/ ) { $positiontemplate = $position; } # setting the position directly, number defined in scp2
else { $positiontemplate = "POSITIONTEMPLATE_" . $position; }
diff --git a/solenv/bin/modules/installer/windows/msiglobal.pm b/solenv/bin/modules/installer/windows/msiglobal.pm
index 383f7f3599cc..d0ddb8920d3d 100644
--- a/solenv/bin/modules/installer/windows/msiglobal.pm
+++ b/solenv/bin/modules/installer/windows/msiglobal.pm
@@ -1009,6 +1009,7 @@ sub set_uuid_into_component_table
# Adding final 64 properties into msi database, if required.
# RegLocator : +16 in type column to search in 64 bit registry.
# All conditions: "VersionNT" -> "VersionNT64" (several tables).
+# DrLocator: "SystemFolder" -> "System64Folder"
# Already done: "+256" in Attributes column of table "Component".
# Still following: Setting "x64" instead of "Intel" in Summary
# Information Stream of msi database in "get_template_for_sis".
@@ -1099,6 +1100,34 @@ sub prepare_64bit_database
}
}
}
+
+ # 3. Replacing all occurrences of "SystemFolder" by "System64Folder" in "DrLocato.idt"
+
+ my $drlocatofilename = $basedir . $installer::globals::separator . "DrLocato.idt";
+ if ( -f $drlocatofilename )
+ {
+ my $saving_required = 0;
+ my $drlocatofile = installer::files::read_file($drlocatofilename);
+
+ for ( my $i = 3; $i <= $#{$drlocatofile}; $i++ ) # ignoring the first three lines
+ {
+ my $oneline = ${$drlocatofile}[$i];
+
+ if ( $oneline =~ /\bSystemFolder\b/ )
+ {
+ ${$drlocatofile}[$i] =~ s/\bSystemFolder\b/System64Folder/g;
+ $saving_required = 1;
+ }
+ }
+
+ if ( $saving_required )
+ {
+ # Saving the files
+ installer::files::save_file($drlocatofilename ,$drlocatofile);
+ $infoline = "Making idt file 64 bit conform: $drlocatofilename\n";
+ push(@installer::globals::logfileinfo, $infoline);
+ }
+ }
}
}