[Libreoffice-commits] core.git: Branch 'distro/cib/libreoffice-5-2' - 58 commits - config_host.mk.in configure.ac cppcanvas/source extensions/Library_so_activex_x64.mk external/msc-externals hwpfilter/source include/o3tl instsetoo_native/inc_openoffice oox/source package/source postprocess/signing pyuno/source RepositoryExternal.mk Repository.mk sal/osl scp2/InstallModule_windows.mk scp2/source sc/qa scripting/source sc/source setup_native/Library_inst_msu_msi.mk setup_native/Module_setup_native.mk setup_native/source sfx2/source solenv/bin solenv/gbuild sot/source svl/source sw/qa sw/source vcl/inc vcl/source vcl/unx writerfilter/source xmloff/source

Michael Stahl (via logerrit) logerrit at kemper.freedesktop.org
Tue Aug 27 13:07:56 UTC 2019


 Repository.mk                                                      |    1 
 RepositoryExternal.mk                                              |    4 
 config_host.mk.in                                                  |    1 
 configure.ac                                                       |   46 
 cppcanvas/source/mtfrenderer/emfplus.cxx                           |   16 
 extensions/Library_so_activex_x64.mk                               |    4 
 external/msc-externals/Module_msc-externals.mk                     |    9 
 external/msc-externals/Package_ucrt.mk                             |   21 
 hwpfilter/source/hcode.cxx                                         |   30 
 hwpfilter/source/hwpfile.h                                         |    2 
 include/o3tl/safeint.hxx                                           |  124 ++
 instsetoo_native/inc_openoffice/windows/msi_templates/AppSearc.idt |    1 
 instsetoo_native/inc_openoffice/windows/msi_templates/Property.idt |    2 
 instsetoo_native/inc_openoffice/windows/msi_templates/RegLocat.idt |    1 
 oox/source/ole/vbacontrol.cxx                                      |   10 
 package/source/zipapi/MemoryByteGrabber.hxx                        |    2 
 package/source/zipapi/ZipFile.cxx                                  |   10 
 postprocess/signing/no_signing.txt                                 |    6 
 pyuno/source/module/pyuno_impl.hxx                                 |    2 
 pyuno/source/module/pyuno_type.cxx                                 |    2 
 pyuno/source/module/pyuno_util.cxx                                 |    2 
 sal/osl/w32/file_dirvol.cxx                                        |   16 
 sc/qa/unit/data/xls/fail/forcepoint-group-range-1.xls              |binary
 sc/qa/unit/data/xls/pass/forcepoint-selfseriesadd.xls              |binary
 sc/source/core/data/column3.cxx                                    |    4 
 sc/source/filter/excel/xichart.cxx                                 |   23 
 sc/source/filter/xml/xmlcelli.cxx                                  |    2 
 sc/source/ui/inc/viewdata.hxx                                      |    4 
 sc/source/ui/view/viewdata.cxx                                     |   12 
 scp2/InstallModule_windows.mk                                      |    1 
 scp2/source/ooo/ucrt.scp                                           |  154 ++
 scp2/source/ooo/vc_redist.scp                                      |   12 
 scp2/source/winexplorerext/file_winexplorerext.scp                 |   11 
 scp2/source/winexplorerext/module_winexplorerext.scp               |    5 
 scripting/source/pyprov/pythonscript.py                            |    5 
 setup_native/Library_inst_msu_msi.mk                               |   40 
 setup_native/Module_setup_native.mk                                |    3 
 setup_native/source/win32/customactions/inst_msu/inst_msu.cxx      |  543 ++++++++++
 setup_native/source/win32/customactions/inst_msu/inst_msu_msi.def  |    5 
 sfx2/source/doc/objmisc.cxx                                        |    2 
 solenv/bin/modules/installer.pm                                    |   26 
 solenv/bin/modules/installer/globals.pm                            |    1 
 solenv/bin/modules/installer/windows/directory.pm                  |   62 +
 solenv/bin/modules/installer/windows/idtglobal.pm                  |   36 
 solenv/bin/modules/installer/windows/update.pm                     |   28 
 solenv/bin/modules/installer/windows/upgrade.pm                    |   12 
 solenv/gbuild/gbuild.mk                                            |    2 
 solenv/gbuild/platform/com_MSC_defs.mk                             |    4 
 solenv/gbuild/platform/windows.mk                                  |   10 
 sot/source/sdstor/stgstrms.cxx                                     |    4 
 svl/source/undo/undo.cxx                                           |    9 
 sw/qa/core/data/odt/fail/forcepoint-dtor-1.odt                     |binary
 sw/qa/core/data/rtf/fail/forcepoint-7.rtf                          |  517 +++++++++
 sw/qa/core/data/rtf/pass/forcepoint-1.rtf                          |  193 +++
 sw/source/core/txtnode/fntcache.cxx                                |    3 
 sw/source/filter/ww8/ww8toolbar.cxx                                |    4 
 sw/source/filter/xml/xmlimp.cxx                                    |    5 
 sw/source/filter/xml/xmltbli.cxx                                   |    7 
 sw/source/filter/xml/xmltexti.cxx                                  |   11 
 vcl/inc/sft.hxx                                                    |   14 
 vcl/source/fontsubset/sft.cxx                                      |  149 +-
 vcl/source/gdi/pdfwriter_impl2.cxx                                 |   27 
 vcl/source/helper/strhelper.cxx                                    |    9 
 vcl/unx/generic/glyphs/freetype_glyphcache.cxx                     |    4 
 vcl/unx/generic/printer/jobdata.cxx                                |   14 
 writerfilter/source/dmapper/DomainMapperTableManager.cxx           |   13 
 writerfilter/source/dmapper/DomainMapperTableManager.hxx           |    1 
 writerfilter/source/dmapper/TableManager.cxx                       |    2 
 writerfilter/source/rtftok/rtfdispatchvalue.cxx                    |    2 
 xmloff/source/draw/ximpcustomshape.cxx                             |    2 
 xmloff/source/text/txtparai.cxx                                    |   15 
 71 files changed, 2139 insertions(+), 185 deletions(-)

New commits:
commit 778de462819c0a2071441622a300ea626c6ed8c8
Author:     Michael Stahl <mstahl at redhat.com>
AuthorDate: Thu Mar 9 18:42:09 2017 +0100
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Aug 27 14:15:33 2019 +0200

    oops, forgot to commit that
    
    Change-Id: I7b0a08ca47996f80112f68daef3e2ba5e3be221b
    (cherry picked from commit 15d46079a5b6429dba0d501e7db218188294587a)

diff --git a/extensions/Library_so_activex_x64.mk b/extensions/Library_so_activex_x64.mk
index e1c4b9a8f9ba..64f644098a8f 100644
--- a/extensions/Library_so_activex_x64.mk
+++ b/extensions/Library_so_activex_x64.mk
@@ -52,7 +52,7 @@ $(eval $(call gb_Library_use_system_win32_libs,so_activex_x64,\
 $(eval $(call gb_Library_add_libs,so_activex_x64,\
 	$(if $(filter 140,$(VCVER)),\
 		$(ATL_LIB)/amd64/atls.lib, \
-		$(subst /x86,/x64,$(ATL_LIB)/amd64/atls.lib)) \
+		$(subst /x86,/x64,$(ATL_LIB)/atls.lib)) \
 ))
 
 # vim:set noet sw=4 ts=4:
commit f8531aa7ea4d108cd78fa1ab924ca35e9677dcfe
Author:     Michael Stahl <mstahl at redhat.com>
AuthorDate: Thu Mar 9 18:40:40 2017 +0100
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Aug 27 14:15:33 2019 +0200

    extensions: fix MSVC 2017 build of Library_so_activex_x64
    
    Change-Id: Ia98c2ba085d6b7705b53dafd5368d69f0e0727c5
    (cherry picked from commit 869a249cebaf58d13812194297561fc361dd3a36)

diff --git a/extensions/Library_so_activex_x64.mk b/extensions/Library_so_activex_x64.mk
index d330ca8a3bf0..e1c4b9a8f9ba 100644
--- a/extensions/Library_so_activex_x64.mk
+++ b/extensions/Library_so_activex_x64.mk
@@ -50,7 +50,9 @@ $(eval $(call gb_Library_use_system_win32_libs,so_activex_x64,\
 ))
 
 $(eval $(call gb_Library_add_libs,so_activex_x64,\
-	$(ATL_LIB)/amd64/atls.lib \
+	$(if $(filter 140,$(VCVER)),\
+		$(ATL_LIB)/amd64/atls.lib, \
+		$(subst /x86,/x64,$(ATL_LIB)/amd64/atls.lib)) \
 ))
 
 # vim:set noet sw=4 ts=4:
commit 393df3fc7d86785a5b6e2e653024e88e7e726b39
Author:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
AuthorDate: Sat May 25 11:12:18 2019 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Aug 27 14:15:33 2019 +0200

    Disable warning C4005 for Vista-compatible SDK 7.1A builds
    
    No point in pulling in all warning fixes from 5.4
    
    Change-Id: I926b2b41628d7059ec9187918ac9df9c1160dfe6

diff --git a/solenv/gbuild/platform/com_MSC_defs.mk b/solenv/gbuild/platform/com_MSC_defs.mk
index ab6f27f6794e..91d2cdc4f218 100644
--- a/solenv/gbuild/platform/com_MSC_defs.mk
+++ b/solenv/gbuild/platform/com_MSC_defs.mk
@@ -152,6 +152,7 @@ gb_CFLAGS := \
 	-nologo \
 	-W4 \
 	-wd4091 \
+       -wd4005 \
 	$(if $(filter 0,$(gb_DEBUGLEVEL)),-wd4100) \
 	-wd4127 \
 	$(if $(filter 0,$(gb_DEBUGLEVEL)),-wd4189) \
@@ -194,6 +195,7 @@ gb_CXXFLAGS := \
 	-nologo \
 	-W4 \
 	-wd4091 \
+       -wd4005 \
 	$(if $(filter 0,$(gb_DEBUGLEVEL)),-wd4100) \
 	-wd4127 \
 	$(if $(filter 0,$(gb_DEBUGLEVEL)),-wd4189) \
@@ -259,7 +261,6 @@ gb_PCHWARNINGS = \
 	-we4651 \
 	-we4652 \
 	-we4653 \
-	-we4005 \
 
 gb_STDLIBS := \
 	advapi32.lib \
commit 072346b581ef1ec330a17bea1ad13ff5e96958a5
Author:     Michael Stahl <mstahl at redhat.com>
AuthorDate: Tue May 30 17:00:42 2017 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Aug 27 14:15:33 2019 +0200

    gbuild: stop defining _USING_V110_SDK71_
    
    Change-Id: Ic8eee967269b3666b15795f20ee62817dadfb0ff
    (cherry picked from commit 713ed7b338b467b176af7eb5e9a80559b8496e8e)

diff --git a/solenv/gbuild/platform/com_MSC_defs.mk b/solenv/gbuild/platform/com_MSC_defs.mk
index cc73510bb451..ab6f27f6794e 100644
--- a/solenv/gbuild/platform/com_MSC_defs.mk
+++ b/solenv/gbuild/platform/com_MSC_defs.mk
@@ -54,7 +54,6 @@ gb_COMPILERDEFS := \
 	-D_MT \
 	-D_DLL \
 	-DCPPU_ENV=$(gb_CPPU_ENV) \
-	$(if $(findstring 140_70,$(VCVER)_$(WINDOWS_SDK_VERSION)),-D_USING_V110_SDK71_) \
 
 ifeq ($(CPUNAME),INTEL)
 gb_COMPILERDEFS += \
commit 3b95330fa357d784b8170c964d247dd4da3552e0
Author:     Michael Stahl <mstahl at redhat.com>
AuthorDate: Tue May 30 16:37:56 2017 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Aug 27 14:15:33 2019 +0200

    gbuild: define _WIN32_WINNT = _WIN32_WINNT_WIN7 = 0x0601
    
    And rely on implicitly derived
    _WIN32_IE = _WIN32_IE_WIN7 = _WIN32_IE_IE80
    
    Change-Id: I94717e2ed66387bdc76f9047c02c0820d4adc1f9
    (cherry picked from commit 2829dabaf37e6d9c736430f3fb9bbfb786b078ad)

diff --git a/solenv/gbuild/platform/windows.mk b/solenv/gbuild/platform/windows.mk
index ebd2a3c86a94..65a4f982320a 100644
--- a/solenv/gbuild/platform/windows.mk
+++ b/solenv/gbuild/platform/windows.mk
@@ -24,13 +24,11 @@ gb_Helper_LIBRARY_PATH_VAR := PATH
 gb_MKTEMP := mktemp --tmpdir=$(gb_TMPDIR) gbuild.XXXXXX
 
 # define _WIN32_WINNT and WINVER will be derived from it in sdkddkver.h
-# with a 7.1 SDK target Windows XP, with 8.x SDK target Windows Vista
-# currently _WIN32_IE is defined to a higher version than would be derived
-# in sdkddkver.h from _WIN32_WINNT=0x0502 but if _WIN32_WINNT >= 0x0600
-# the derived value is sufficient
+# current baseline is Windows 7 (NT 6.1)
+# for _WIN32_IE, if _WIN32_WINNT >= 0x0600 the derived value from
+# sdkddkver.h is sufficient
 gb_OSDEFS := \
-	-D_WIN32_WINNT=$(if $(filter 70,$(WINDOWS_SDK_VERSION)),0x0502,0x0600) \
-	-D_WIN32_IE=0x0700 \
+	-D_WIN32_WINNT=0x0601 \
 	-DWIN32 \
 	-DWNT \
 	-DNOMINMAX \
commit 03f6c8496b8008175346d2b754f921e10f9a950b
Author:     Michael Stahl <mstahl at redhat.com>
AuthorDate: Fri Jun 2 22:38:06 2017 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Aug 27 14:15:33 2019 +0200

    scp2: package 64-bit MSVC runtimes for explorer extensions
    
    Not a backport because master is a bit too refactored now.
    
    Reviewed-on: https://gerrit.libreoffice.org/38365
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Michael Stahl <mstahl at redhat.com>
    (cherry picked from commit ab4344c34ddf048adf9a3fad0dd1fa2970935550)
    
    Conflicts:
            scp2/source/winexplorerext/file_winexplorerext.scp
    
    Change-Id: I1eccb99252fb66dc1fcc9cb5af978c61717ff629

diff --git a/scp2/source/winexplorerext/file_winexplorerext.scp b/scp2/source/winexplorerext/file_winexplorerext.scp
index 7567896b4b9f..7ca1f9c6a63d 100644
--- a/scp2/source/winexplorerext/file_winexplorerext.scp
+++ b/scp2/source/winexplorerext/file_winexplorerext.scp
@@ -85,4 +85,15 @@ End
 
 #endif
 
+#if defined(WITH_VC140_REDIST) || defined(WITH_VC150_REDIST)
+
+File gid_File_X64_Redist
+    Styles = (FILELIST, USE_INTERNAL_RIGHTS, PACKED);
+    Dir = FILELIST_DIR;
+    Name = "msvc_dlls.filelist";
+    ComponentCondition = "VersionNT64";
+End
+
+#endif
+
 #endif
diff --git a/scp2/source/winexplorerext/module_winexplorerext.scp b/scp2/source/winexplorerext/module_winexplorerext.scp
index 440945e89096..b71153cd0052 100644
--- a/scp2/source/winexplorerext/module_winexplorerext.scp
+++ b/scp2/source/winexplorerext/module_winexplorerext.scp
@@ -49,9 +49,6 @@ Module gid_Module_Optional_Winexplorerext_x64
     Dirs = (gid_Dir_Shlxthdl);
     Files = (auto_winexplorerextwin64_ALL,
              auto_winexplorerextwin64nt6_ALL,
-             gid_File_Lib_Msvcp100,
-             gid_File_Lib_Msvcr100,
-             gid_File_Lib_Msvcp110,
-             gid_File_Lib_Msvcr110);
+             gid_File_X64_Redist);
 End
 #endif
commit 602367f6375ff43f24ba156492b790ed126ec388
Author:     David Ostrovsky <david at ostrovsky.org>
AuthorDate: Sat Jan 21 11:44:33 2017 +0100
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Aug 27 14:15:32 2019 +0200

    tdf#105311 VC++ Runtime installed in wrong directory
    
    Starting from MSVC 14.0, the directory table layout of VC++ Runtime merge
    module changed. As consequence, all MSI produced with newer compilers,
    including MSVC 15.0 (aka VS 2017) are broken in term that the VC++
    Runtime DLLs are installed in the wrong directory, e.g.: C:\System64.
    
    According to the specification for merging merge module (msm), see:
    "Authoring Merge Module Directory Tables": [1], custom action 51 (set
    property) must be emitted for every directory name in the merge module
    directory table if the directory name is starting with the standard
    directory name.
    
    Quoting it here:
    
    "
    When a predefined directory is included in a merge module, the merge
    tool automatically adds a Custom Action Type 51 to the target database.
    The merge module author must ensure that a CustomAction table is also
    included. The CustomAction table may be empty, but this table is required
    to exist in the target database and ensures that the modified predefined
    directories are written to the correct locations. For example, when a
    system directory is included in a merge module, the merge module author
    must ensure that a Custom Action table exists.
    
    Note that the matching algorithm for the generation of these type 51
    custom actions only checks that the directory name begins with one of
    the predefined SystemFolder properties. It does not verify that the
    directory name exactly equals the directory property. Any directory
    beginning with one of these standard folder names gets a type 51 custom
    action, even if the rest of the name is not a GUID. Authors need to take
    care that this does not generate false positive matches, and unintended
    custom action generation, on derivative primary keys that begin with one
    of the SystemFolder properties."
    
    Rectify the problem by analyzing the directory table from the merge
    module, checking whether the directory name starts with the standard
    prefix name and if it is the case, emitting custom action 51 to set this
    variable to the standard directory name.
    
    Implementation details:
    
    We use the existing facility for emitting the custom action table events
    including referencing them in the corresponding sequence tables. Given
    that the specification above doesn't mention what sequence table should
    be referencing this emitted custom action, we reversed engineer this
    information from WiX toolkit. Merging the VC++ CRT module with WiX
    toolkit and investigating the resulting MSI with Orca MSI reader, reveals
    that these sequence tables were referencing from these sequence tables:
    
    * AdminExecuteSequence
    * AdminUISequence
    * AdvtExecuteSequence
    * InstallExecuteSequence
    * InstallUISequence
    
    Replicate this behaviour here as well. Note, though, that custom actions
    are generally not referenced in AdminUISequence and AdvtExecuteSequence
    tables in LibreOffice MSI building tool chain.
    
    Rendering of the custom action is achieved by programmatic emulation of
    custom action in SCP module. Consider this similar SCP module based
    action:
    
      Name = "MigrateInstallPath";
      Typ = "321";
      Source = "shlxtmsi.dll";
      Target = "MigrateInstallPath";
      Inbinarytable = 1;
      Assignment1 = ("InstallExecuteSequence", "", "CostInitialize");
      Assignment2 = ("InstallUISequence", "", "CostInitialize");
    
    We instantiate the following data structure to emit custom action
    System64Folder.3CFBED52_9B44_3A4D_953C_90E456671BA1:
    
      Name = "System64Folder.3CFBED52_9B44_3A4D_953C_90E456671BA1"
      Typ = "51"
      Source = "System64Folder.3CFBED52_9B44_3A4D_953C_90E456671BA1"
      Target = "[System64Folder]"
      Styles = "NO_FILES"
      Assignment1 = ("AdminExecuteSequence", "", "CostInitialize")
      Assignment2 = ("InstallExecuteSequence", "", "CostInitialize")
      Assignment3 = ("InstallUISequence", "", "CostInitialize")
    
    [1] https://msdn.microsoft.com/en-us/library/windows/desktop/aa367787%28v=vs.85%29.aspx
    
    Change-Id: I2fbd37ff63298d99b2ba1b6afe6e875f56d8e378
    Reviewed-on: https://gerrit.libreoffice.org/33366
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: David Ostrovsky <david at ostrovsky.org>
    (cherry picked from commit 30473907a565764eb35a19051dc0d52704cf7bb7)

diff --git a/solenv/bin/modules/installer.pm b/solenv/bin/modules/installer.pm
index 605aec25e663..eb6ec70aafb9 100644
--- a/solenv/bin/modules/installer.pm
+++ b/solenv/bin/modules/installer.pm
@@ -519,9 +519,15 @@ sub run {
                 if ( $installer::globals::updatedatabase )
                 {
                     ($uniquefilename, $revuniquefilename, $revshortfilename, $allupdatesequences, $allupdatecomponents, $allupdatefileorder, $allupdatecomponentorder, $shortdirname, $componentid, $componentidkeypath, $alloldproperties, $allupdatelastsequences, $allupdatediskids) = installer::windows::update::create_database_hashes($refdatabase);
-                    if ( $mergemodulesarrayref > -1 ) { installer::windows::update::readmergedatabase($mergemodulesarrayref, $languagestringref, $includepatharrayref); }
                 }
             }
+
+            # Always analyze the merge module.
+            # We need to investigate the directory table in merge module to emit
+            # custom action for directory names that start with standard prefix
+            if ( $mergemodulesarrayref > -1 ) {
+                installer::windows::update::readmergedatabase($mergemodulesarrayref, $languagestringref, $includepatharrayref);
+            }
         }
 
         ##############################################
@@ -1510,6 +1516,24 @@ sub run {
 
                 installer::windows::idtglobal::addcustomactions($languageidtdir, $windowscustomactionsarrayref, $filesinproductlanguageresolvedarrayref);
 
+                installer::logger::print_message( "... Analyze if custom action table must be patched with merge module directory names ...\n" );
+
+                my @customactions = ();
+                for my $e (keys %installer::globals::merge_directory_hash) {
+                    my $var;
+                    installer::logger::print_message( "... analyzing directory from merge module: $e\n");
+                    if (installer::windows::directory::has_standard_directory_prefix($e, \$var)) {
+                        installer::logger::print_message( "... emitting custom action to set the var $e to directory: $var\n");
+                        push(@customactions, installer::windows::idtglobal::emit_custom_action_for_standard_directory($e, $var));
+                    }
+                }
+
+                if (@customactions) {
+                    installer::logger::print_message( "... Patching custom action table with merge module directory names ...\n" );
+                    #print Dumper(@customactions);
+                    installer::windows::idtglobal::addcustomactions($languageidtdir, \@customactions, $filesinproductlanguageresolvedarrayref);
+                }
+
                 # Then the language specific msi database can be created
 
                 if ( $installer::globals::iswin || $installer::globals::packageformat eq 'msi' )
diff --git a/solenv/bin/modules/installer/globals.pm b/solenv/bin/modules/installer/globals.pm
index 5a7423aa48f8..c09b696c766c 100644
--- a/solenv/bin/modules/installer/globals.pm
+++ b/solenv/bin/modules/installer/globals.pm
@@ -159,6 +159,7 @@ BEGIN
     %merge_media_line = ();
     %merge_allfeature_hash = ();
     %merge_alldirectory_hash = ();
+    %merge_directory_hash = ();
     %copy_msm_files = ();
     $mergefeaturecollected = 0;
     $mergedirectoriescollected = 0;
diff --git a/solenv/bin/modules/installer/windows/directory.pm b/solenv/bin/modules/installer/windows/directory.pm
index a1d677393334..b29fa13c045a 100644
--- a/solenv/bin/modules/installer/windows/directory.pm
+++ b/solenv/bin/modules/installer/windows/directory.pm
@@ -29,6 +29,36 @@ use installer::windows::msiglobal;
 # Collecting all directory trees in global hash
 ##############################################################
 
+my @msistandarddirectorynames = qw(
+   AdminToolsFolder
+   AppDataFolder
+   CommonAppDataFolder
+   CommonFiles64Folder
+   CommonFilesFolder
+   DesktopFolder
+   FavoritesFolder
+   FontsFolder
+   LocalAppDataFolder
+   MyPicturesFolder
+   NetHoodFolder
+   PersonalFolder
+   PrintHoodFolder
+   ProgramFiles64Folder
+   ProgramFilesFolder
+   ProgramMenuFolder
+   RecentFolder
+   SendToFolder
+   StartMenuFolder
+   StartupFolder
+   System16Folder
+   System64Folder
+   SystemFolder
+   TempFolder
+   TemplateFolder
+   WindowsFolder
+   WindowsVolume
+);
+
 sub collectdirectorytrees
 {
     my ( $directoryref ) = @_;
@@ -569,4 +599,36 @@ sub create_directory_table
     }
 }
 
+################################################
+# Check if the string starts with another string
+################################################
+
+sub starts_with
+{
+    my ($first, $second) = @_;
+
+    return substr($first, 0, length($second)) eq $second;
+}
+
+###############################################
+# Check if the directory prefix is a standard
+# directory name. If it is the case, then the
+# standard directory name is returned in $var.
+###############################################
+
+sub has_standard_directory_prefix
+{
+    my ($dir, $var) = @_;
+
+    for my $d (@msistandarddirectorynames) {
+        if (starts_with($dir, $d) && $dir ne $d) {
+            installer::logger::print_message("... match found: [$d]\n");
+            ${$var} = $d;
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
 1;
diff --git a/solenv/bin/modules/installer/windows/idtglobal.pm b/solenv/bin/modules/installer/windows/idtglobal.pm
index d9d2f9e2c238..2fa46fbbdb6a 100644
--- a/solenv/bin/modules/installer/windows/idtglobal.pm
+++ b/solenv/bin/modules/installer/windows/idtglobal.pm
@@ -1834,4 +1834,29 @@ sub setbidiattributes
     push(@installer::globals::logfileinfo, $infoline);
 }
 
+###############################################
+# Emit custom action 51 for setting standard
+# directory variable. Reference to a hash is
+# returned, represented the custom action.
+# This can be passed in to addcustomaction
+# method.
+###############################################
+
+sub emit_custom_action_for_standard_directory
+{
+    my ($dir, $var) = @_;
+    my %action = ();
+
+    $action{'Name'} = $dir;
+    $action{'Typ'} = "51";
+    $action{'Source'} = $dir;
+    $action{'Target'} = "[$var]";
+    $action{'Styles'} = "NO_FILE";
+    $action{'Assignment1'} = '("AdminExecuteSequence", "", "CostInitialize")';
+    $action{'Assignment2'} = '("InstallExecuteSequence", "", "CostInitialize")';
+    $action{'Assignment3'} = '("InstallUISequence", "", "CostInitialize")';
+
+    return \%action;
+}
+
 1;
diff --git a/solenv/bin/modules/installer/windows/update.pm b/solenv/bin/modules/installer/windows/update.pm
index 0edaaf2d8d91..45c47ed7ab0d 100644
--- a/solenv/bin/modules/installer/windows/update.pm
+++ b/solenv/bin/modules/installer/windows/update.pm
@@ -183,6 +183,9 @@ sub read_all_tables_from_msidatabase
         if ( ! -f $longonefilename ) { installer::exiter::exit_program("ERROR: Could not find idt file: $longonefilename!", "read_all_tables_from_msidatabase"); }
         my $filecontent = installer::files::read_file($longonefilename);
         my $idtcontent = analyze_idt_file($filecontent);
+        if ($onefilename eq "Directory.idt") {
+            collect_directories($filecontent);
+        }
         my $key = $onefilename;
         $key =~ s/\.idt\s*$//;
         $database{$key} = $idtcontent;
@@ -406,6 +409,31 @@ sub readdatabase
     return $database;
 }
 
+#########################################################################
+# Reading the file "Directory.idt".
+#########################################################################
+
+sub collect_directories
+{
+    my ($filecontent) = @_;
+
+    for ( my $i = 0; $i <= $#{$filecontent}; $i++ )
+    {
+        if ( $i <= 2 ) { next; }                        # ignoring first three lines
+        if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines
+        # Format: Directory Directory_Parent    DefaultDir
+        if ( ${$filecontent}[$i] =~ /^\s*(.+?)\t(.*?)\t(.*?)\s*$/ )
+        {
+            $installer::globals::merge_directory_hash{$1} = 1;
+        }
+        else
+        {
+            my $linecount = $i + 1;
+            installer::exiter::exit_program("ERROR: Unknown line format in table \"$idtfilename\" (line $linecount) !", "collect_directories");
+        }
+    }
+}
+
 #################################################################################
 # Files can be included in merge modules. This is also important for update.
 #################################################################################
commit ae4faee498f9c026db898c0e232f09f4efaf4299
Author:     Stephan Bergmann <sbergman at redhat.com>
AuthorDate: Tue Jul 3 08:33:34 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Aug 27 14:15:32 2019 +0200

    const fixes for python3-devel-3.7.0-1.fc29.x86_64
    
    Change-Id: Ia16a8b828e11ce36e9bb77ecf9e8a1179bd9b90c
    Reviewed-on: https://gerrit.libreoffice.org/56841
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <sbergman at redhat.com>
    (cherry picked from commit 76a29148be63cb006a7e25e312dc93acc93e071f)

diff --git a/pyuno/source/module/pyuno_impl.hxx b/pyuno/source/module/pyuno_impl.hxx
index 0452da7cef6f..4a12ad3136d2 100644
--- a/pyuno/source/module/pyuno_impl.hxx
+++ b/pyuno/source/module/pyuno_impl.hxx
@@ -80,7 +80,7 @@ inline PyObject* PyStr_FromString(const char *string)
     return PyUnicode_FromString(string);
 }
 
-inline char * PyStr_AsString(PyObject *object)
+inline char const * PyStr_AsString(PyObject *object)
 {
     return PyUnicode_AsUTF8(object);
 }
diff --git a/pyuno/source/module/pyuno_type.cxx b/pyuno/source/module/pyuno_type.cxx
index c2472e478029..f35ddf4ace6d 100644
--- a/pyuno/source/module/pyuno_type.cxx
+++ b/pyuno/source/module/pyuno_type.cxx
@@ -155,7 +155,7 @@ Any PyEnum2Enum( PyObject *obj ) throw ( RuntimeException )
     }
 
     OUString strTypeName( OUString::createFromAscii( PyStr_AsString( typeName.get() ) ) );
-    char *stringValue = PyStr_AsString( value.get() );
+    char const *stringValue = PyStr_AsString( value.get() );
 
     TypeDescription desc( strTypeName );
     if( desc.is() )
diff --git a/pyuno/source/module/pyuno_util.cxx b/pyuno/source/module/pyuno_util.cxx
index ede4cd6f01c0..8e3d74287421 100644
--- a/pyuno/source/module/pyuno_util.cxx
+++ b/pyuno/source/module/pyuno_util.cxx
@@ -64,7 +64,7 @@ OUString pyString2ustring( PyObject *pystr )
 #else
 #if PY_MAJOR_VERSION >= 3
     Py_ssize_t size(0);
-    char *pUtf8(PyUnicode_AsUTF8AndSize(pystr, &size));
+    char const *pUtf8(PyUnicode_AsUTF8AndSize(pystr, &size));
     ret = OUString(pUtf8, size, RTL_TEXTENCODING_UTF8);
 #else
     PyObject* pUtf8 = PyUnicode_AsUTF8String(pystr);
commit 8bc2c89a998d41c7bca314a13b33f5311639b810
Author:     Mike Kaganski <mike.kaganski at collabora.com>
AuthorDate: Mon Dec 17 00:23:24 2018 +0300
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Aug 27 14:15:32 2019 +0200

    tdf#122134: use CurrentMajorVersionNumber to filter out Windows 10
    
    On Windows 8.1, the one that is problematic to tell from Windows 10
    (because the latter also exposes its version as 603 to the msiexec),
    the registry value doesn't exist at
    HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion
    but let's play safe and also check for "#6" value just in case.
    
    Reference:
    https://stackoverflow.com/questions/31072543/reliable-way-to-get-windows-version-from-registry
    
    Thanks to Mitchell <blazer64 at gmail.com> for the idea!
    
    Reviewed-on: https://gerrit.libreoffice.org/65231
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>
    Tested-by: Mike Kaganski <mike.kaganski at collabora.com>
    (cherry picked from commit d87fa557ff58c3b9f5c9079a1d7595e095694111)
    Reviewed-on: https://gerrit.libreoffice.org/65242
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>
    (cherry picked from commit 72f2fbc75dc254ea8e13527b592bd0b4fb946bab)
    
    Conflicts:
            instsetoo_native/inc_openoffice/windows/msi_templates/AppSearc.idt
    
    Change-Id: Ic907c4d992a7cb1d12e392686c19cd6fd6da3c7c

diff --git a/instsetoo_native/inc_openoffice/windows/msi_templates/AppSearc.idt b/instsetoo_native/inc_openoffice/windows/msi_templates/AppSearc.idt
index 3968375a8815..4bc5b05f6d9a 100644
--- a/instsetoo_native/inc_openoffice/windows/msi_templates/AppSearc.idt
+++ b/instsetoo_native/inc_openoffice/windows/msi_templates/AppSearc.idt
@@ -5,3 +5,4 @@ INSTALLLOCATION	installuser
 INSTALLLOCATION	installuser_
 INSTALLLOCATION	installmachine
 INSTALLLOCATION	installmachine_
+WINMAJORVER	WinMajorVer
diff --git a/instsetoo_native/inc_openoffice/windows/msi_templates/Property.idt b/instsetoo_native/inc_openoffice/windows/msi_templates/Property.idt
index 44fb9f500387..b3eaa2342d9f 100644
--- a/instsetoo_native/inc_openoffice/windows/msi_templates/Property.idt
+++ b/instsetoo_native/inc_openoffice/windows/msi_templates/Property.idt
@@ -42,7 +42,7 @@ ProgressType3	installs
 Quickstarterlinkname	QUICKSTARTERLINKNAMETEMPLATE
 RebootYesNo	Yes
 ReinstallModeText	omus
-SecureCustomProperties	NEWPRODUCTS;OLDPRODUCTS;WIN81S14
+SecureCustomProperties	NEWPRODUCTS;OLDPRODUCTS;WIN81S14;WINMAJORVER
 SetupType	Typical
 SELECT_WORD	0
 SELECT_EXCEL	0
diff --git a/instsetoo_native/inc_openoffice/windows/msi_templates/RegLocat.idt b/instsetoo_native/inc_openoffice/windows/msi_templates/RegLocat.idt
index c082322086ad..7788815d3a6e 100644
--- a/instsetoo_native/inc_openoffice/windows/msi_templates/RegLocat.idt
+++ b/instsetoo_native/inc_openoffice/windows/msi_templates/RegLocat.idt
@@ -5,3 +5,4 @@ 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
+WinMajorVer	2	Software\Microsoft\Windows NT\CurrentVersion	CurrentMajorVersionNumber	2
diff --git a/scp2/source/ooo/ucrt.scp b/scp2/source/ooo/ucrt.scp
index ae2eb27a4dbe..a2d6965e2ecb 100644
--- a/scp2/source/ooo/ucrt.scp
+++ b/scp2/source/ooo/ucrt.scp
@@ -111,7 +111,7 @@ WindowsCustomAction gid_Customaction_check_win81x64_ucrt
 	Source = "InstMSUBinary";
 	Target = "Windows81-KB2999226-x64msu";
 	Inbinarytable = 0;
-	Assignment1 = ("InstallExecuteSequence", "Not Installed And VersionNT = 603 And VersionNT64", "check_win8x64_ucrt");
+	Assignment1 = ("InstallExecuteSequence", "Not Installed And VersionNT = 603 And (Not WINMAJORVER Or WINMAJORVER = \"#6\") And VersionNT64", "check_win8x64_ucrt");
 	Styles = "NO_FILE";
 End
 
@@ -147,7 +147,7 @@ WindowsCustomAction gid_Customaction_check_win81x32_ucrt
 	Source = "InstMSUBinary";
 	Target = "Windows81-KB2999226-x86msu";
 	Inbinarytable = 0;
-	Assignment1 = ("InstallExecuteSequence", "Not Installed And VersionNT = 603 And Not VersionNT64", "check_win8x32_ucrt");
+	Assignment1 = ("InstallExecuteSequence", "Not Installed And VersionNT = 603 And (Not WINMAJORVER Or WINMAJORVER = \"#6\") And Not VersionNT64", "check_win8x32_ucrt");
 	Styles = "NO_FILE";
 End
 
commit 4f6363922f6da07edfb3998b56f6a55e5ff409cf
Author:     Mike Kaganski <mike.kaganski at collabora.com>
AuthorDate: Thu Apr 12 15:18:58 2018 +0300
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Aug 27 14:15:32 2019 +0200

    tdf#108580 related: improve existing redist detection
    
    This uses VC Runtime upgrade code (checked using Upgrade table) to
    find installed redist, instead of checking registry keys that change
    between versions (while the runtime is still compatible, as with 2015
    and 2017).
    Also, it checks if UCRT is present. Now, if either VC Runtime or UCRT
    is absent, we try to install the redist. This would allow to install
    UCRT in scenarios when first install was attempted on a system not
    suitable for UCRT (like Win7 w/o SP1, or Win8.1 w/o April 2014 update
    rollup), where VC Runtime gets installed, but UCRT is still missing.
    We use the ucrtbase.dll version to check that; and as the expected
    version is 10.x, we take into account that Win10 lies about versions.
    
    Reviewed-on: https://gerrit.libreoffice.org/52794
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>
    (cherry picked from commit 1f8a3657216e44796cb94087450552aa977ebdae)
    
    Conflicts:
            instsetoo_native/inc_openoffice/windows/msi_templates/DrLocato.idt
    
    Change-Id: I864dfc09cf1bdc775501729fa2a27dc98295588c

diff --git a/solenv/bin/modules/installer/windows/upgrade.pm b/solenv/bin/modules/installer/windows/upgrade.pm
index 54838212404c..9e0d7ea79fb7 100644
--- a/solenv/bin/modules/installer/windows/upgrade.pm
+++ b/solenv/bin/modules/installer/windows/upgrade.pm
@@ -45,6 +45,18 @@ sub create_upgrade_table
     $newline = $installer::globals::upgradecode . "\t" . $installer::globals::msiproductversion . "\t" . "\t" . "\t" . "2" . "\t" . "\t" . "NEWPRODUCTS" . "\n";
     push(@upgradetable, $newline);
 
+    # Detecting if VC Runtime is installed on system
+    $newline = "VCRUNTIME_UPGRADE_CODE" . "\t" . "14.0.24215" . "\t" . "15.0.0" . "\t" . "" . "\t" . "258" . "\t" . "" . "\t" . "VCRUNTIME_DETECTED";
+    if ( $installer::globals::cpuname eq 'X86_64' )
+    {
+        $newline =~ s/VCRUNTIME_UPGRADE_CODE/{36F68A90-239C-34DF-B58C-64B30153CE35}/;
+    }
+    else
+    {
+        $newline =~ s/VCRUNTIME_UPGRADE_CODE/{65E5BD06-6392-3027-8C26-853107D3CF1A}/;
+    }
+    push(@upgradetable, $newline);
+
     # Saving the file
 
     my $upgradetablename = $basedir . $installer::globals::separator . "Upgrade.idt";
commit 4fbf13fa0a79200d129e5dcc8e298da58e4446be
Author:     Mike Kaganski <mike.kaganski at collabora.com>
AuthorDate: Sat Dec 8 23:35:37 2018 +0300
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Aug 27 14:15:32 2019 +0200

    tdf#121987: Don't fail installation if failed to enable WU service
    
    Since commit 1882827320ed760de82211cf690b686f8d34ff74, an attempt to
    install UCRT will be performed regardless there is an evidence that it's
    present on the system, to workaround some cases where the existing UCRT
    is broken (tdf#115405, tdf#119910).
    
    But that made other errors to emerge: on systems where users disable WU
    service using some exotic ways, installer is unable to enable the
    service, and fails. [1][2] Examples of such hard-disables are using
    `sc delete` [3] and associating WU service with a guest account. Many
    such cases are reported for Windows 10, where installation of the UCRT
    is not required.
    
    So the solution (imperfect, but possibly the best possible here) is to
    allow installer to continue in case of failure enabling the service.
    This will automatically eliminate all problems related to Win10; and
    also for cases where users are advanced enough (the majority of such
    hard-disable cases should be those), it might be enough to add a
    relevant FAQ entry.
    
    [1] https://ask.libreoffice.org/en/question/172227/cannot-install-631/
    [2] https://ask.libreoffice.org/en/question/175571/installation-failed-unknown-error-win10x64/
    [3] https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/sc-delete
    
    Change-Id: Ie85016eb6f0667f39412a3089fe1b1855cb1fc73
    Reviewed-on: https://gerrit.libreoffice.org/64825
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>
    Tested-by: Mike Kaganski <mike.kaganski at collabora.com>
    (cherry picked from commit 53058090beede6a399e2f408f62c28a2921ff8ab)
    Reviewed-on: https://gerrit.libreoffice.org/64829
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/setup_native/source/win32/customactions/inst_msu/inst_msu.cxx b/setup_native/source/win32/customactions/inst_msu/inst_msu.cxx
index b03d3cf3791c..fe948a97d595 100644
--- a/setup_native/source/win32/customactions/inst_msu/inst_msu.cxx
+++ b/setup_native/source/win32/customactions/inst_msu/inst_msu.cxx
@@ -166,6 +166,16 @@ bool IsWow64Process()
 #endif
 }
 
+// An exception class to differentiate a non-fatal exception
+class nonfatal_exception : public std::exception
+{
+public:
+    nonfatal_exception(const std::exception& e)
+        : std::exception(e)
+    {
+    }
+};
+
 // Checks if Windows Update service is disabled, and if it is, enables it temporarily.
 class WUServiceEnabler
 {
@@ -195,27 +205,37 @@ public:
 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))
+        try
         {
-            // No need to restore anything back, since we didn't change config
-            hService.reset();
-            WriteLog(hInstall, "Service configuration is unchanged");
-        }
+            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;
+            return hService;
+        }
+        catch (const std::exception& e)
+        {
+            // Allow errors opening service to be logged, but not interrupt installation.
+            // They are likely to happen in situations where people hard-disable WU service,
+            // and for these cases, let people deal with install logs instead of failing.
+            throw nonfatal_exception(e);
+        }
     }
 
     // Returns if the service configuration was actually changed
@@ -476,6 +496,14 @@ extern "C" UINT __stdcall InstallMSU(MSIHANDLE hInstall)
                 ThrowWin32Error("Execution of wusa.exe", nExitCode);
         }
     }
+    catch (nonfatal_exception& e)
+    {
+        // An error that should not interrupt installation
+        WriteLog(hInstall, e.what());
+        WriteLog(hInstall, "Installation of MSU package failed, but installation of product will "
+                           "continue. You may need to install the required update manually");
+        return ERROR_SUCCESS;
+    }
     catch (std::exception& e)
     {
         WriteLog(hInstall, e.what());
commit 74c722ad010bac861cc528e57dba9ff5177016a6
Author:     Mike Kaganski <mike.kaganski at collabora.com>
AuthorDate: Thu Sep 20 08:05:41 2018 +0300
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Aug 27 14:15:32 2019 +0200

    tdf#115405, tdf#119910: don't check if UCRT is already installed
    
    There appears to be common situation that a system has *some* UCRT libraries
    in System32, that were installed improperly (presumably by some applications
    using simple copy).In these cases, our installer would detect the presence of
    ucrtbase.dll, and not try to install UCRT on the system.
    
    Unfortunately, it seems that oftentimes such improper UCRT installations miss
    some parts of UCRT, which leads to LibreOffice failing to start with messages
    like "The program can't start because api-ms-win-crt-string-l1-1-0.dll is
    missing from your computer. Try reinstalling the program to fix this problem."
    (the missing component varies).
    
    This patch removes the check for UCRT presence. Installer will try to install
    UCRT on applicable systems unconditionally. Since the proper outcomes in case
    of already present UCRT are either WU_S_ALREADY_INSTALLED or WU_E_NOT_APPLICABLE
    and both are treated as success in inst_msu action (see InstallMSU in
    setup_native/source/win32/customactions/inst_msu/inst_msu.cxx), this should
    only make this part more robust, and not bring new problems (yes, I know that
    actually there will be new problems, as usual).
    
    Reviewed-on: https://gerrit.libreoffice.org/60789
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>
    (cherry picked from commit 1882827320ed760de82211cf690b686f8d34ff74)
    Reviewed-on: https://gerrit.libreoffice.org/61444
    Reviewed-by: Christian Lohmaier <lohmaier+LibreOffice at googlemail.com>
    
    Change-Id: I22a3d357014d31a8e492ff8a15bcb477eeb79735

diff --git a/instsetoo_native/inc_openoffice/windows/msi_templates/Property.idt b/instsetoo_native/inc_openoffice/windows/msi_templates/Property.idt
index f51e12ed0d60..44fb9f500387 100644
--- a/instsetoo_native/inc_openoffice/windows/msi_templates/Property.idt
+++ b/instsetoo_native/inc_openoffice/windows/msi_templates/Property.idt
@@ -42,7 +42,7 @@ ProgressType3	installs
 Quickstarterlinkname	QUICKSTARTERLINKNAMETEMPLATE
 RebootYesNo	Yes
 ReinstallModeText	omus
-SecureCustomProperties	NEWPRODUCTS;OLDPRODUCTS;WIN81S14;UCRT_DETECTED
+SecureCustomProperties	NEWPRODUCTS;OLDPRODUCTS;WIN81S14
 SetupType	Typical
 SELECT_WORD	0
 SELECT_EXCEL	0
diff --git a/scp2/source/ooo/ucrt.scp b/scp2/source/ooo/ucrt.scp
index 4a13309f6364..ae2eb27a4dbe 100644
--- a/scp2/source/ooo/ucrt.scp
+++ b/scp2/source/ooo/ucrt.scp
@@ -91,7 +91,7 @@ WindowsCustomAction gid_Customaction_check_win7x64_ucrt
 	Source = "InstMSUBinary";
 	Target = "Windows61-KB2999226-x64msu";
 	Inbinarytable = 0;
-	Assignment1 = ("InstallExecuteSequence", "Not Installed And VersionNT = 601 And VersionNT64 And Not UCRT_DETECTED", "FileCost");
+	Assignment1 = ("InstallExecuteSequence", "Not Installed And VersionNT = 601 And VersionNT64", "FileCost");
 	Styles = "NO_FILE";
 End
 
@@ -101,7 +101,7 @@ WindowsCustomAction gid_Customaction_check_win8x64_ucrt
 	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");
+	Assignment1 = ("InstallExecuteSequence", "Not Installed And VersionNT = 602 And VersionNT64", "check_win7x64_ucrt");
 	Styles = "NO_FILE";
 End
 
@@ -111,7 +111,7 @@ WindowsCustomAction gid_Customaction_check_win81x64_ucrt
 	Source = "InstMSUBinary";
 	Target = "Windows81-KB2999226-x64msu";
 	Inbinarytable = 0;
-	Assignment1 = ("InstallExecuteSequence", "Not Installed And VersionNT = 603 And VersionNT64 And Not UCRT_DETECTED", "check_win8x64_ucrt");
+	Assignment1 = ("InstallExecuteSequence", "Not Installed And VersionNT = 603 And VersionNT64", "check_win8x64_ucrt");
 	Styles = "NO_FILE";
 End
 
@@ -127,7 +127,7 @@ WindowsCustomAction gid_Customaction_check_win7x32_ucrt
 	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");
+	Assignment1 = ("InstallExecuteSequence", "Not Installed And VersionNT = 601 And Not VersionNT64", "check_win81x64_ucrt");
 	Styles = "NO_FILE";
 End
 
@@ -137,7 +137,7 @@ WindowsCustomAction gid_Customaction_check_win8x32_ucrt
 	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");
+	Assignment1 = ("InstallExecuteSequence", "Not Installed And VersionNT = 602 And Not VersionNT64", "check_win7x32_ucrt");
 	Styles = "NO_FILE";
 End
 
@@ -147,7 +147,7 @@ WindowsCustomAction gid_Customaction_check_win81x32_ucrt
 	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");
+	Assignment1 = ("InstallExecuteSequence", "Not Installed And VersionNT = 603 And Not VersionNT64", "check_win8x32_ucrt");
 	Styles = "NO_FILE";
 End
 
commit f249f39e59a2a28ebdcd6055c5c73e634890134e
Author:     Mike Kaganski <mike.kaganski at collabora.com>
AuthorDate: Mon Jul 30 14:46:41 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Aug 27 14:15:32 2019 +0200

    tdf#118869: mark some properties secure to pass them to elevated install
    
    See also http://helpnet.flexerasoftware.com/installshield19helplib/helplibrary/ISBP10.htm
    
    Change-Id: I217d68f98af8e56874af6c071bb7fa7354b3e4b4
    Reviewed-on: https://gerrit.libreoffice.org/58326
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>
    (cherry picked from commit ec9b18b75c193c914691a29d3eb78bd81961fced)
    Reviewed-on: https://gerrit.libreoffice.org/58338
    Reviewed-by: Christian Lohmaier <lohmaier+LibreOffice at googlemail.com>

diff --git a/instsetoo_native/inc_openoffice/windows/msi_templates/Property.idt b/instsetoo_native/inc_openoffice/windows/msi_templates/Property.idt
index b771f8bc706e..f51e12ed0d60 100644
--- a/instsetoo_native/inc_openoffice/windows/msi_templates/Property.idt
+++ b/instsetoo_native/inc_openoffice/windows/msi_templates/Property.idt
@@ -42,7 +42,7 @@ ProgressType3	installs
 Quickstarterlinkname	QUICKSTARTERLINKNAMETEMPLATE
 RebootYesNo	Yes
 ReinstallModeText	omus
-SecureCustomProperties	NEWPRODUCTS;OLDPRODUCTS
+SecureCustomProperties	NEWPRODUCTS;OLDPRODUCTS;WIN81S14;UCRT_DETECTED
 SetupType	Typical
 SELECT_WORD	0
 SELECT_EXCEL	0
commit 7fa58bb1c59fd31bfda4d26d7aef5e849fb4c8d2
Author:     Mike Kaganski <mike.kaganski at collabora.com>
AuthorDate: Sun Apr 15 23:24:42 2018 +0300
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Aug 27 14:15:31 2019 +0200

    Install UCRT from MSUs, not using nested VC Redist install
    
    Using nested install is bad because (1) MS advises against it (though it
    most possibly doesn't relate to our specific case, when we install the
    vc redist exe package in UI part, so actually only a single MSI session
    is active at any time); (2) because it adds some extra interactions
    (user sees something "unrelated" being installed, which raises concerns;
    additional admin authentication required); and (3) because it runs in
    InstallUISequence, thus only installing the UCRT when doing interactive
    installation (unattended installs, including GPO, need to install UCRT
    separately).
    
    This patch aims to incorporate the original UCRT MSU (Windows Update)
    packages (https://support.microsoft.com/en-us/help/2999226) available as
    a zip archive from
    https://www.microsoft.com/en-us/download/details.aspx?id=48234
    - the same as used in VC redists for VS 2015 and 2017. This obsoletes
    the separate installation of the redist; since we also have the redist
    as merge module in our MSI, that is enough (and removes redundancy).
    The MSUs are installed using wusa.exe in a custom action (deferred,
    non-impersonating).
    
    As a small bonus, embedding MSUs instead of redist EXE allows us to
    shrink the size of installer a little (~10 MB).
    
    As deferred custom actions cannot access current installer database,
    we workaround this by using initial immediate impersonating action to
    extract the binaries into a temporary location. To ensure that the file
    gets removed upon completion (both successful and failed), we use an
    additional cleanup action.
    
    Commit 61b1d631331551b43bc7d619be33bfbfeff7cad6 is effectively reverted.
    
    Change-Id: I1529356fdcc67ff24b232c01ddf8bb3a31bb00bd
    Reviewed-on: https://gerrit.libreoffice.org/52923
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>

diff --git a/Repository.mk b/Repository.mk
index 0204b9138f02..de328943a601 100644
--- a/Repository.mk
+++ b/Repository.mk
@@ -637,6 +637,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 22fd07859a54..32a5cbf98682 100644
--- a/RepositoryExternal.mk
+++ b/RepositoryExternal.mk
@@ -3980,4 +3980,8 @@ $(call gb_LinkTarget_set_include,$(1), \
 $(call gb_LinkTarget_use_libraries,$(1),clew)
 endef
 
+$(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 04fc400554fa..9f6ab639cc47 100644
--- a/config_host.mk.in
+++ b/config_host.mk.in
@@ -599,6 +599,7 @@ export TOUCH=@TOUCH@
 export TYPO_EXTENSION_PACK=@TYPO_EXTENSION_PACK@
 export UCRTSDKDIR=@UCRTSDKDIR@
 export UCRTVERSION=@UCRTVERSION@
+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 e7f466668268..d8209e033e9d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6946,6 +6946,21 @@ fi
 AC_SUBST([JITC_PROCESSOR_TYPE])
 
 # Misc Windows Stuff
+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]),
+,)
+UCRT_REDISTDIR="$with_ucrt_dir"
 if test $_os = "WINNT" -a "$WITH_MINGW" != yes; then
     find_msvc_x64_dlls
     find_msms
@@ -6953,8 +6968,39 @@ if test $_os = "WINNT" -a "$WITH_MINGW" != yes; then
     MSVC_DLLS="$msvcdlls"
     MSM_PATH="$msmdir"
     SCPDEFS="$SCPDEFS -DWITH_VC${VCVER}_REDIST"
+
+    # MSVC 15.3 changed it to VC141
+    if echo "$MSVC_DLL_PATH" | grep -q "VC141.CRT$"; then
+        SCPDEFS="$SCPDEFS -DWITH_VC141_REDIST"
+    else
+        SCPDEFS="$SCPDEFS -DWITH_VC${VCVER}_REDIST"
+    fi
+    if test "$UCRT_REDISTDIR" = "no"; then
+        dnl explicitly disabled
+        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-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
+            fi
+        fi
+    fi
 fi
 
+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 002dcf5cc0b9..c926f9d4b829 100644
--- a/external/msc-externals/Module_msc-externals.mk
+++ b/external/msc-externals/Module_msc-externals.mk
@@ -14,4 +14,13 @@ $(eval $(call gb_Module_add_targets,msc-externals,\
 	Package_msvc_dlls \
 ))
 
+# Install the universal crts (tdf#108580)
+ifneq ($(UCRT_REDISTDIR),)
+
+$(eval $(call gb_Module_add_targets,msc-externals,\
+	Package_ucrt \
+))
+
+endif
+
 # vim: set noet sw=4 ts=4:
diff --git a/external/msc-externals/Package_ucrt.mk b/external/msc-externals/Package_ucrt.mk
new file mode 100644
index 000000000000..52e6f0cbae97
--- /dev/null
+++ b/external/msc-externals/Package_ucrt.mk
@@ -0,0 +1,21 @@
+# -*- 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_Package_Package,ucrt,$(UCRT_REDISTDIR)))
+
+$(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/postprocess/signing/no_signing.txt b/postprocess/signing/no_signing.txt
index 26ba6aab7e92..f13ea7273699 100644
--- a/postprocess/signing/no_signing.txt
+++ b/postprocess/signing/no_signing.txt
@@ -9,3 +9,9 @@ policy.1.0.cli_ure.dll
 policy.1.0.cli_cppuhelper.dll
 policy.1.0.cli_basetypes.dll
 mingwm10.dll
+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 296f7fccfa5b..bd6e478e7785 100644
--- a/scp2/InstallModule_windows.mk
+++ b/scp2/InstallModule_windows.mk
@@ -22,6 +22,7 @@ $(eval $(call gb_InstallModule_add_defs,scp2/windows,\
 $(eval $(call gb_InstallModule_add_scpfiles,scp2/windows,\
     scp2/source/ooo/folder_ooo \
     $(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 23214f0e2eaa..4d9da6acdf55 100644
--- a/scp2/source/ooo/vc_redist.scp
+++ b/scp2/source/ooo/vc_redist.scp
@@ -18,17 +18,6 @@
 
 #include "macros.inc"
 
-#if defined(WITH_VC100_REDIST)
-
-MergeModule gid_MergeModule_Microsoft_VC100_CRT_x86
-    Feature = gm_Root;
-    Name = "Microsoft_VC100_CRT_x86.msm";
-    RootDir = "TARGETDIR";
-    ComponentCondition = "VC_REDIST=1";
-End
-
-#endif
-
 #if defined(WITH_VC110_REDIST)
 
 MergeModule gid_MergeModule_Microsoft_VC110_CRT_x86
@@ -77,4 +66,3 @@ MergeModule gid_MergeModule_Microsoft_VC140_CRT_x86
 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 d0f935e26240..7bb1d94a6245 100644
--- a/setup_native/Module_setup_native.mk
+++ b/setup_native/Module_setup_native.mk
@@ -29,7 +29,8 @@ endif
 
 ifeq ($(OS)$(COM),WNTMSC)
 $(eval $(call gb_Module_add_targets,setup_native,\
-        Library_instooofiltmsi \
+	Library_instooofiltmsi \
+	Library_inst_msu_msi \
 	Library_qslnkmsi \
 	Library_reg4allmsdoc \
 	$(if $(DISABLE_ACTIVEX),,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 8cbfcb24b2b8..d9d2f9e2c238 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; }
commit 531057e6d4c25ffba059e3e92127c960c19bf032
Author:     Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
AuthorDate: Tue Jan 15 16:09:24 2019 +0100
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Aug 27 14:13:54 2019 +0200

    Remove unreachable code
    
    VS 2015 won't compile because of this
    
    Change-Id: I4244ccd6d5dbbedef536ea8782afd3a8f2abf3a9
    Reviewed-on: https://gerrit.libreoffice.org/66395
    Reviewed-by: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
    Tested-by: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>

diff --git a/svl/source/undo/undo.cxx b/svl/source/undo/undo.cxx
index 58320a1e2744..dd40901c0826 100644
--- a/svl/source/undo/undo.cxx
+++ b/svl/source/undo/undo.cxx
@@ -393,14 +393,7 @@ namespace svl { namespace undo { namespace impl
         {
             SfxUndoAction* pAction = m_aUndoActionsCleanup.front();
             m_aUndoActionsCleanup.pop_front();
-            try
-            {
-                delete pAction;
-            }
-            catch( const Exception& )
-            {
-                DBG_UNHANDLED_EXCEPTION();
-            }
+            delete pAction;
         }
 
         // handle scheduled notification
commit 464881d3e3b30f5b26a0eb74b5f9f86e5651c47b
Author:     Stephan Bergmann <sbergman at redhat.com>
AuthorDate: Wed Aug 17 13:35:58 2016 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Aug 27 14:13:54 2019 +0200

    "make debug=t" enables debuginfo again
    
    ...which had inadvertently been broken with
    99db9f2295eb9a8b3288df9798a292b8d6e1b854 "Make --enable-symbols orthogonal to
    --enable-debug/-dbgutil"
    
    Change-Id: I3962aa8c67426f3aebc5ad746f7ac281c68d941a
    (cherry picked from commit 62c4a8aacf76771e97a8da35096e6ad69a11979a)

diff --git a/solenv/gbuild/gbuild.mk b/solenv/gbuild/gbuild.mk
index 04056cd136c8..5b81c37549cf 100644
--- a/solenv/gbuild/gbuild.mk
+++ b/solenv/gbuild/gbuild.mk
@@ -87,12 +87,14 @@ gb_DEBUGLEVEL := 1
 # make DEBUG=true should force -g
 ifeq ($(origin DEBUG),command line)
 ENABLE_DEBUGINFO_FOR := all
+ENABLE_SYMBOLS := TRUE
 endif
 endif
 ifneq ($(strip $(debug)),)
 gb_DEBUGLEVEL := 1
 ifeq ($(origin debug),command line)
 ENABLE_DEBUGINFO_FOR := all
+ENABLE_SYMBOLS := TRUE
 endif
 endif
 ifeq ($(gb_ENABLE_DBGUTIL),$(true))
commit 7d57196beb094e80178e33e08a79ddc64e4c4b4e
Author:     Caolán McNamara <caolanm at redhat.com>
AuthorDate: Fri Feb 9 10:35:33 2018 +0000
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Aug 27 14:12:29 2019 +0200

    various sft fixes
    
    backport removing unneeded code
    
    use ptr diff rather than int
    
    (cherry picked from commit 5b426038a7befcaf0d05824ffb20200ff8833ad3)
    
    fix mem leak
    
    (cherry picked from commit 603cb6cf31a5212d03736a552770e5734b0e8066)
    
    check more table sizes
    
    (cherry picked from commit 1828490bb22f1c8273c4a9f5b1db819b173ca70d)
    
    check cmap offset
    
    (cherry picked from commit 683d9883ad8fd6568e6a7832e5bb347c1d043e4b)
    
    check tableoffset against size
    
    (cherry picked from commit ae73c3ff112e1ed38eb4678ac5745990661a2e66)
    
    check ntables offset
    
    (cherry picked from commit 75a171a405afd6eac236af93aa9d29a9c3ec9c64)
    
    use safeint on calculations
    
    (cherry picked from commit 139b6c6cf898467098f3a6f29fa84013a182285f)
    
    simplify returns
    
    (cherry picked from commit e8b2aad1cb2107304761e68aa380b5c29d8ef22f)
    
    extend to cover the last byte needed
    
    (cherry picked from commit c7b0117f26a386c98a721ff3897479c268103d74)
    
    bounds check
    
    (cherry picked from commit bb32616bdd6e3b327654bab0e1d790d8d50b893d)
    
    move largest bounds check to start
    
    (cherry picked from commit f832198e6a33052c7cc86b25843badfb962a2ae8)
    
    android:update safeint header to use the else implementation with clang
    
    Clang toolchain does not defines the __builtin_mul_overflow for 32-bit
    ARM. So, fallback to else implementation of checked_multiply when
    building Android with Clang
    
    Reviewed-on: https://gerrit.libreoffice.org/39005
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    (cherry picked from commit 2149d4a88e9dc88c30e7475f8ea317e5c7b78529)
    
    add checked_add
    
    Reviewed-on: https://gerrit.libreoffice.org/43779
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>
    (cherry picked from commit 9cfb27ae6cb94f0a853ff70e9ad9f3109d305a94)
    
    Change-Id: I0b59f1b93d31a7cb5b8db2a21736db11aed46536
    a174fd94c57cc3c899c10e1c0dc5968965a50427
    0d329357ac282d4652b0f7ebc401cbd51963461b
    004a6d322f60d916cc4635b362ce948e8a10d7c7
    5aae26c38f3645020f0e1d6d7b6877c2727af1b4
    a79be052dd3f6b6ed38fb326558924c853af5fff
    d75f5f4b578fd176c17e5763569f1403260c6594
    c063786ba41aa9a985f505e62b43d3d543a0d48f
    1a67cb2f1c686032438852fec1267a59fbd04d7f
    5177d42b47a4bca614878dce4a69ab16b5cfe163
    6d32a6b6f1dd91db42a3f154700ea55603f0e4dd
    03fe80f9568759b829fac4e9bcfd496efebe6a26
    6120606f521ce121541a5b7f1150229258012d55
    10cba898bba528f5f1bfbd583e27a6821c789ab9
    Reviewed-on: https://gerrit.libreoffice.org/49485
    Reviewed-by: Michael Stahl <mstahl at redhat.com>
    Tested-by: Jenkins <ci at libreoffice.org>

diff --git a/include/o3tl/safeint.hxx b/include/o3tl/safeint.hxx
new file mode 100644
index 000000000000..5ebf353b6bd6
--- /dev/null
+++ b/include/o3tl/safeint.hxx
@@ -0,0 +1,124 @@
+/* -*- 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/.
+ */
+
+#ifndef INCLUDED_O3TL_SAFEINT_HXX
+#define INCLUDED_O3TL_SAFEINT_HXX
+
+#include <limits>
+#if defined(_MSC_VER)
+#include <safeint.h>
+#else
+#ifndef __has_builtin
+#   define __has_builtin(x) 0
+#endif
+#endif
+
+namespace o3tl
+{
+
+#if defined(_MSC_VER)
+
+template<typename T> inline bool checked_multiply(T a, T b, T& result)
+{
+    return !msl::utilities::SafeMultiply(a, b, result);
+}
+
+template<typename T> inline bool checked_add(T a, T b, T& result)
+{
+    return !msl::utilities::SafeAdd(a, b, result);
+}
+
+#elif (defined __GNUC__ && __GNUC__ >= 5) || (__has_builtin(__builtin_mul_overflow) && !(defined ANDROID && defined __clang__))
+
+template<typename T> inline bool checked_multiply(T a, T b, T& result)
+{
+    return __builtin_mul_overflow(a, b, &result);
+}
+
+template<typename T> inline bool checked_add(T a, T b, T& result)
+{
+    return __builtin_add_overflow(a, b, &result);
+}
+
+#else
+
+//https://www.securecoding.cert.org/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow
+template<typename T> inline typename std::enable_if<std::is_signed<T>::value, bool>::type checked_multiply(T a, T b, T& result)
+{
+  if (a > 0) {  /* a is positive */
+    if (b > 0) {  /* a and b are positive */
+      if (a > (std::numeric_limits<T>::max() / b)) {
+        return true; /* Handle error */
+      }
+    } else { /* a positive, b nonpositive */
+      if (b < (std::numeric_limits<T>::min() / a)) {
+        return true; /* Handle error */
+      }
+    } /* a positive, b nonpositive */
+  } else { /* a is nonpositive */
+    if (b > 0) { /* a is nonpositive, b is positive */
+      if (a < (std::numeric_limits<T>::min() / b)) {
+        return true; /* Handle error */
+      }
+    } else { /* a and b are nonpositive */
+      if ( (a != 0) && (b < (std::numeric_limits<T>::max() / a))) {
+        return true; /* Handle error */
+      }
+    } /* End if a and b are nonpositive */
+  } /* End if a is nonpositive */
+
+  result = a * b;
+
+  return false;
+}
+
+//https://www.securecoding.cert.org/confluence/display/c/INT30-C.+Ensure+that+unsigned+integer+operations+do+not+wrap
+template<typename T> inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type checked_multiply(T a, T b, T& result)
+{
+    if (b && a > std::numeric_limits<T>::max() / b) {
+        return true;/* Handle error */
+    }
+
+    result = a * b;
+
+    return false;
+}
+
+//https://www.securecoding.cert.org/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow
+template<typename T> inline typename std::enable_if<std::is_signed<T>::value, bool>::type checked_add(T a, T b, T& result)
+{
+    if (((b > 0) && (a > (std::numeric_limits<T>::max() - b))) ||
+        ((b < 0) && (a < (std::numeric_limits<T>::min() - b)))) {
+        return true;
+    }
+
+    result = a + b;
+
+    return false;
+}
+
+//https://www.securecoding.cert.org/confluence/display/c/INT30-C.+Ensure+that+unsigned+integer+operations+do+not+wrap
+template<typename T> inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type checked_add(T a, T b, T& result)
+{
+    if (std::numeric_limits<T>::max() - a < b) {
+        return true;/* Handle error */
+    }
+
+    result = a + b;
+
+    return false;
+}
+
+#endif
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/sft.hxx b/vcl/inc/sft.hxx
index 80c62c11b878..0b3c3afcfbef 100644
--- a/vcl/inc/sft.hxx
+++ b/vcl/inc/sft.hxx
@@ -189,21 +189,15 @@ namespace vcl
         int   descender;          /**< typographic descent.                                    */
         int   linegap;            /**< typographic line gap.\ Negative values are treated as
                                      zero in Win 3.1, System 6 and System 7.                 */
-        int   vascent;            /**< typographic ascent for vertical writing mode            */
-        int   vdescent;           /**< typographic descent for vertical writing mode           */
         int   typoAscender;       /**< OS/2 portable typographic ascender                      */
         int   typoDescender;      /**< OS/2 portable typographic descender                     */
         int   typoLineGap;        /**< OS/2 portable typographic line gap                       */
         int   winAscent;          /**< ascender metric for Windows                             */
         int   winDescent;         /**< descender metric for Windows                            */
         bool  symbolEncoded;      /**< true: MS symbol encoded */
-        int   rangeFlag;          /**< if set to 1 Unicode Range flags are applicable          */
-        sal_uInt32 ur1;               /**< bits 0 - 31 of Unicode Range flags                      */
-        sal_uInt32 ur2;               /**< bits 32 - 63 of Unicode Range flags                     */
-        sal_uInt32 ur3;               /**< bits 64 - 95 of Unicode Range flags                     */
-        sal_uInt32 ur4;               /**< bits 96 - 127 of Unicode Range flags                    */
-        sal_uInt8   panose[10];        /**< PANOSE classification number                            */
-        sal_uInt32 typeFlags;         /**< type flags (copyright bits + PS-OpenType flag)       */
+        sal_uInt8  panose[10];    /**< PANOSE classification number                            */
+        sal_uInt32 typeFlags;     /**< type flags (copyright bits + PS-OpenType flag)       */
+        sal_uInt16 fsSelection;   /**< OS/2 fsSelection */
     } TTGlobalFontInfo;
 
 #define TYPEFLAG_INVALID        0x8000000
@@ -521,8 +515,6 @@ namespace vcl
 /*- private definitions */
 
     struct TrueTypeFont {
-        sal_uInt32 tag;
-
         char        *fname;
         sal_Int32   fsize;
         sal_uInt8   *ptr;
diff --git a/vcl/source/fontsubset/sft.cxx b/vcl/source/fontsubset/sft.cxx
index 150b21ec676a..e6bfd7509da3 100644
--- a/vcl/source/fontsubset/sft.cxx
+++ b/vcl/source/fontsubset/sft.cxx
@@ -39,7 +39,7 @@
 #include "xlat.hxx"
 #include <rtl/crc.h>
 #include <rtl/ustring.hxx>
-
+#include <o3tl/safeint.hxx>
 #include <osl/endian.h>
 #include <algorithm>
 
@@ -104,9 +104,6 @@ typedef struct {
     sal_uInt32 *offs;             /* array of nGlyphs offsets */
 } GlyphOffsets;
 
-/* private tags */
-static const sal_uInt32 TTFontClassTag = 0x74746663;  /* 'ttfc' */
-
 static const sal_uInt32 T_true = 0x74727565;        /* 'true' */
 static const sal_uInt32 T_ttcf = 0x74746366;        /* 'ttcf' */
 static const sal_uInt32 T_otto = 0x4f54544f;        /* 'OTTO' */
@@ -1341,6 +1338,13 @@ static void FindCmap(TrueTypeFont *ttf)
     }
 
     if (ttf->cmapType != CMAP_NOT_USABLE) {
+        if( (ttf->cmap - ttf->ptr + 2U) > static_cast<sal_uInt32>(ttf->fsize) ) {
+            ttf->cmapType = CMAP_NOT_USABLE;
+            ttf->cmap = nullptr;
+        }
+    }
+
+    if (ttf->cmapType != CMAP_NOT_USABLE) {
         switch (GetUInt16(ttf->cmap, 0, 1)) {
             case 0: ttf->mapper = getGlyph0; break;
             case 2: ttf->mapper = getGlyph2; break;
@@ -1461,7 +1465,6 @@ static void allocTrueTypeFont( TrueTypeFont** ttf )
     *ttf = static_cast<TrueTypeFont*>(calloc(1,sizeof(TrueTypeFont)));
     if( *ttf != nullptr )
     {
-        (*ttf)->tag = 0;
         (*ttf)->fname = nullptr;
         (*ttf)->fsize = -1;
         (*ttf)->ptr = nullptr;
@@ -1546,10 +1549,41 @@ int OpenTTFontBuffer(const void* pBuffer, sal_uInt32 nLen, sal_uInt32 facenum, T
     return doOpenTTFont( facenum, *ttf );
 }
 
+namespace {
+
+bool withinBounds(sal_uInt32 tdoffset, sal_uInt32 moreoffset, sal_uInt32 len, sal_uInt32 available)
+{
+    sal_uInt32 result;
+    if (o3tl::checked_add(tdoffset, moreoffset, result))
+        return false;
+    if (o3tl::checked_add(result, len, result))
+        return false;
+    return result <= available;
+}
+
+class TTFontCloser
+{
+    TrueTypeFont* m_font;
+public:
+    TTFontCloser(TrueTypeFont* t)
+        : m_font(t)
+    {
+    }
+    void clear() { m_font = nullptr; }
+    ~TTFontCloser()
+    {
+        if (m_font)
+            CloseTTFont(m_font);
+    }
+};
+
+}
+
 static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t )
 {
+    TTFontCloser aCloseGuard(t);
+
     if (t->fsize < 4) {
-        CloseTTFont(t);
         return SF_TTFORMAT;
     }
     int i;
@@ -1563,27 +1597,28 @@ static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t )
     } else if (TTCTag == T_otto) {                         /* PS-OpenType font */
         tdoffset = 0;
     } else if (TTCTag == T_ttcf) {                         /* TrueType collection */
+        if (!withinBounds(12, 4 * facenum, sizeof(sal_uInt32), t->fsize)) {
+            return SF_FONTNO;
+        }
         sal_uInt32 Version = GetUInt32(t->ptr, 4, 1);
         if (Version != 0x00010000 && Version != 0x00020000) {
-            CloseTTFont(t);
             return SF_TTFORMAT;
         }
         if (facenum >= GetUInt32(t->ptr, 8, 1)) {
-            CloseTTFont(t);
             return SF_FONTNO;
         }
         tdoffset = GetUInt32(t->ptr, 12 + 4 * facenum, 1);
     } else {
-        CloseTTFont(t);
         return SF_TTFORMAT;
     }
 
-    /* magic number */
-    t->tag = TTFontClassTag;
+    if (withinBounds(tdoffset, 0, 4 + sizeof(sal_uInt16), t->fsize)) {
+        t->ntables = GetUInt16(t->ptr + tdoffset, 4, 1);
+    }
 
-    t->ntables = GetUInt16(t->ptr + tdoffset, 4, 1);
-    if( t->ntables >= 128 )
+    if (t->ntables >= 128 || t->ntables == 0) {
         return SF_TTFORMAT;
+    }
 
     t->tables = static_cast<const sal_uInt8**>(calloc(NUM_TAGS, sizeof(sal_uInt8 *)));
     assert(t->tables != nullptr);
@@ -1595,7 +1630,7 @@ static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t )
         int nIndex;
         const sal_uInt32 nStart = tdoffset + 12;
         const sal_uInt32 nOffset = 16 * i;
-        if (nStart + nOffset + sizeof(sal_uInt32) <=  static_cast<sal_uInt32>(t->fsize))
+        if (withinBounds(nStart, nOffset, sizeof(sal_uInt32), t->fsize))
             tag = GetUInt32(t->ptr + nStart, nOffset, 1);
         else
             tag = static_cast<sal_uInt32>(-1);
@@ -1620,9 +1655,10 @@ static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t )
             case T_CFF:  nIndex = O_CFF; break;
             default: nIndex = -1; break;
         }
-        if( nIndex >= 0 ) {
-            sal_uInt32 nTableOffset = GetUInt32(t->ptr + tdoffset + 12, 16 * i + 8, 1);
-            length = GetUInt32(t->ptr + tdoffset + 12, 16 * i + 12, 1);
+
+        if ((nIndex >= 0) && withinBounds(nStart, nOffset, 12 + sizeof(sal_uInt32), t->fsize)) {
+            sal_uInt32 nTableOffset = GetUInt32(t->ptr + nStart, nOffset + 8, 1);
+            length = GetUInt32(t->ptr + nStart, nOffset + 12, 1);
             t->tables[nIndex] = t->ptr + nTableOffset;
             t->tlens[nIndex] = length;
         }
@@ -1631,8 +1667,9 @@ static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t )
     /* Fixup offsets when only a TTC extract was provided */
     if( facenum == (sal_uInt32)~0 ) {
         sal_uInt8* pHead = const_cast<sal_uInt8*>(t->tables[O_head]);
-        if( !pHead )
+        if (!pHead) {
             return SF_TTFORMAT;
+        }
         /* limit Head candidate to TTC extract's limits */
         if( pHead > t->ptr + (t->fsize - 54) )
             pHead = t->ptr + (t->fsize - 54);
@@ -1648,8 +1685,9 @@ static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t )
                 break;
             }
         }
-        if( p <= t->ptr )
+        if (p <= t->ptr) {
             return SF_TTFORMAT;
+        }
     }
 
     /* Check the table offsets after TTC correction */
@@ -1671,7 +1709,7 @@ static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t )
         }
         else if( const_cast<sal_uInt8*>(t->tables[i]) + t->tlens[i] > t->ptr + t->fsize )
         {
-            int nMaxLen = (t->ptr + t->fsize) - t->tables[i];
+            sal_PtrDiff nMaxLen = (t->ptr + t->fsize) - t->tables[i];
             if( nMaxLen < 0 )
                 nMaxLen = 0;
             t->tlens[i] = nMaxLen;
@@ -1689,7 +1727,6 @@ static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t )
      */
 
     if( !(getTable(t, O_maxp) && getTable(t, O_head) && getTable(t, O_name) && getTable(t, O_cmap)) ) {
-        CloseTTFont(t);
         return SF_TTFORMAT;
     }
 
@@ -1700,14 +1737,12 @@ static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t )
     table = getTable(t, O_head);
     table_size = getTableSize(t, O_head);
     if (table_size < 52) {
-        CloseTTFont(t);
         return SF_TTFORMAT;
     }
     t->unitsPerEm = GetUInt16(table, 18, 1);
     int indexfmt = GetInt16(table, 50, 1);
 
     if( ((indexfmt != 0) && (indexfmt != 1)) || (t->unitsPerEm <= 0) ) {
-        CloseTTFont(t);
         return SF_TTFORMAT;
     }
 
@@ -1731,7 +1766,6 @@ static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t )
         /* TODO: implement to get subsetting */
         assert(t->goffsets != nullptr);
     } else {
-        CloseTTFont(t);
         return SF_TTFORMAT;
     }
 
@@ -1748,6 +1782,8 @@ static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t )
     GetKern(t);
     ReadGSUB( t, 0, 0 );
 
+    aCloseGuard.clear();
+

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list