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 <[email protected]> AuthorDate: Thu Mar 9 18:42:09 2017 +0100 Commit: Michael Stahl <[email protected]> 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 <[email protected]> AuthorDate: Thu Mar 9 18:40:40 2017 +0100 Commit: Michael Stahl <[email protected]> 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 <[email protected]> AuthorDate: Sat May 25 11:12:18 2019 +0200 Commit: Michael Stahl <[email protected]> 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 <[email protected]> AuthorDate: Tue May 30 17:00:42 2017 +0200 Commit: Michael Stahl <[email protected]> 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 <[email protected]> AuthorDate: Tue May 30 16:37:56 2017 +0200 Commit: Michael Stahl <[email protected]> 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 <[email protected]> AuthorDate: Fri Jun 2 22:38:06 2017 +0200 Commit: Michael Stahl <[email protected]> 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 <[email protected]> Reviewed-by: Michael Stahl <[email protected]> (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 <[email protected]> AuthorDate: Sat Jan 21 11:44:33 2017 +0100 Commit: Michael Stahl <[email protected]> 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 <[email protected]> Reviewed-by: David Ostrovsky <[email protected]> (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 <[email protected]> AuthorDate: Tue Jul 3 08:33:34 2018 +0200 Commit: Michael Stahl <[email protected]> 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 <[email protected]> (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 <[email protected]> AuthorDate: Mon Dec 17 00:23:24 2018 +0300 Commit: Michael Stahl <[email protected]> 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 <[email protected]> for the idea! Reviewed-on: https://gerrit.libreoffice.org/65231 Reviewed-by: Mike Kaganski <[email protected]> Tested-by: Mike Kaganski <[email protected]> (cherry picked from commit d87fa557ff58c3b9f5c9079a1d7595e095694111) Reviewed-on: https://gerrit.libreoffice.org/65242 Tested-by: Jenkins Reviewed-by: Caolán McNamara <[email protected]> Tested-by: Caolán McNamara <[email protected]> (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 <[email protected]> AuthorDate: Thu Apr 12 15:18:58 2018 +0300 Commit: Michael Stahl <[email protected]> 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 <[email protected]> Reviewed-by: Mike Kaganski <[email protected]> (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 <[email protected]> AuthorDate: Sat Dec 8 23:35:37 2018 +0300 Commit: Michael Stahl <[email protected]> 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 <[email protected]> Tested-by: Mike Kaganski <[email protected]> (cherry picked from commit 53058090beede6a399e2f408f62c28a2921ff8ab) Reviewed-on: https://gerrit.libreoffice.org/64829 Tested-by: Jenkins Reviewed-by: Caolán McNamara <[email protected]> Tested-by: Caolán McNamara <[email protected]> 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 <[email protected]> AuthorDate: Thu Sep 20 08:05:41 2018 +0300 Commit: Michael Stahl <[email protected]> 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 <[email protected]> (cherry picked from commit 1882827320ed760de82211cf690b686f8d34ff74) Reviewed-on: https://gerrit.libreoffice.org/61444 Reviewed-by: Christian Lohmaier <[email protected]> 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 <[email protected]> AuthorDate: Mon Jul 30 14:46:41 2018 +0200 Commit: Michael Stahl <[email protected]> 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 <[email protected]> (cherry picked from commit ec9b18b75c193c914691a29d3eb78bd81961fced) Reviewed-on: https://gerrit.libreoffice.org/58338 Reviewed-by: Christian Lohmaier <[email protected]> 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 <[email protected]> AuthorDate: Sun Apr 15 23:24:42 2018 +0300 Commit: Michael Stahl <[email protected]> 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 <[email protected]> Reviewed-by: Mike Kaganski <[email protected]> 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 <[email protected]> AuthorDate: Tue Jan 15 16:09:24 2019 +0100 Commit: Michael Stahl <[email protected]> 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 <[email protected]> Tested-by: Samuel Mehrbrodt <[email protected]> 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 <[email protected]> AuthorDate: Wed Aug 17 13:35:58 2016 +0200 Commit: Michael Stahl <[email protected]> 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 <[email protected]> AuthorDate: Fri Feb 9 10:35:33 2018 +0000 Commit: Michael Stahl <[email protected]> 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 <[email protected]> Reviewed-by: Miklos Vajna <[email protected]> (cherry picked from commit 2149d4a88e9dc88c30e7475f8ea317e5c7b78529) add checked_add Reviewed-on: https://gerrit.libreoffice.org/43779 Tested-by: Jenkins <[email protected]> Reviewed-by: Caolán McNamara <[email protected]> Tested-by: Caolán McNamara <[email protected]> (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 <[email protected]> Tested-by: Jenkins <[email protected]> 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 _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
