diff options
-rw-r--r-- | Repository.mk | 1 | ||||
-rw-r--r-- | external/onlineupdate/Library_install_updateservice.mk | 54 | ||||
-rw-r--r-- | external/onlineupdate/Module_onlineupdate.mk | 1 | ||||
-rw-r--r-- | external/onlineupdate/install_updateservice.cxx | 179 | ||||
-rw-r--r-- | external/onlineupdate/install_updateservice.def | 4 | ||||
-rw-r--r-- | scp2/source/ooo/windowscustomaction_ooo.scp | 23 |
6 files changed, 262 insertions, 0 deletions
diff --git a/Repository.mk b/Repository.mk index 9ef08e814a20..a53d923f36b5 100644 --- a/Repository.mk +++ b/Repository.mk @@ -743,6 +743,7 @@ $(eval $(call gb_Helper_register_libraries_for_install,PLAINLIBS_OOO,ooobinaryta sdqsmsi \ sellangmsi \ sn_tools \ + $(if $(ENABLE_ONLINE_UPDATE_MAR),install_updateservice) \ ) \ )) diff --git a/external/onlineupdate/Library_install_updateservice.mk b/external/onlineupdate/Library_install_updateservice.mk new file mode 100644 index 000000000000..216b81a95a07 --- /dev/null +++ b/external/onlineupdate/Library_install_updateservice.mk @@ -0,0 +1,54 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*- +# +# 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,install_updateservice)) + +$(eval $(call gb_Library_use_unpacked,install_updateservice,onlineupdate)) + +$(eval $(call gb_Library_set_include,install_updateservice, \ + -I$(call gb_UnpackedTarball_get_dir,onlineupdate)/onlineupdate/source/update/common \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_Library_add_defs,install_updateservice, \ + -U_DLL \ +)) + +$(eval $(call gb_Library_add_cxxflags,install_updateservice, \ + $(if $(MSVC_USE_DEBUG_RUNTIME),/MTd,/MT) \ + $(if $(filter -fsanitize=%,$(CC)),,/fno-sanitize-address-vcasan-lib) \ +)) + +$(eval $(call gb_Library_add_ldflags,install_updateservice, \ + /DEF:$(SRCDIR)/external/onlineupdate/install_updateservice.def \ + /NODEFAULTLIB \ +)) + +$(eval $(call gb_Library_add_exception_objects,install_updateservice, \ + external/onlineupdate/install_updateservice \ +)) + +$(eval $(call gb_Library_use_static_libraries,install_updateservice, \ + updatehelper \ +)) + +$(eval $(call gb_Library_use_system_win32_libs,install_updateservice, \ + libcmt \ + libcpmt \ + libucrt \ + libvcruntime \ + msi \ + kernel32 \ + user32 \ + advapi32 \ + shell32 \ + shlwapi \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/external/onlineupdate/Module_onlineupdate.mk b/external/onlineupdate/Module_onlineupdate.mk index a6bc698aa3ca..97f7d5c3f7bd 100644 --- a/external/onlineupdate/Module_onlineupdate.mk +++ b/external/onlineupdate/Module_onlineupdate.mk @@ -18,6 +18,7 @@ $(eval $(call gb_Module_add_targets,onlineupdate,\ StaticLibrary_updatehelper \ $(if $(filter WNT,$(OS)),\ Executable_update_service \ + Library_install_updateservice \ WinResTarget_updater )\ Executable_test_updater_dialog \ Executable_mar \ diff --git a/external/onlineupdate/install_updateservice.cxx b/external/onlineupdate/install_updateservice.cxx new file mode 100644 index 000000000000..4604e55462d6 --- /dev/null +++ b/external/onlineupdate/install_updateservice.cxx @@ -0,0 +1,179 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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 <sal/config.h> + +#include <cstddef> +#include <limits> +#include <memory> +#include <string> + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <msiquery.h> + +#include <pathhash.h> + +// Replacements for functions used in +// workdir/UnpackedTarball/onlineupdate/onlineupdate/source/update/common/pathhash.cpp but not +// available here: + +extern "C" wchar_t* _wcslwr(wchar_t* str) +{ + for (auto p = str; *p != L'\0'; ++p) + { + if (*p >= L'A' && *p <= L'Z') + { + *p += L'a' - L'A'; + } + } + return str; +}; + +extern "C" wchar_t* wcsncpy(wchar_t* strDest, wchar_t const* strSource, std::size_t count) +{ + for (std::size_t i = 0; i != count; ++i) + { + strDest[i] = *strSource; + if (*strSource != L'\0') + { + ++strSource; + } + } + return strDest; +} + +namespace +{ +bool getInstallLocation(MSIHANDLE handle, std::wstring* installLocation) +{ + DWORD n = 0; + if (MsiGetPropertyW(handle, L"INSTALLLOCATION", const_cast<wchar_t*>(L""), &n) + != ERROR_MORE_DATA + || n == std::numeric_limits<DWORD>::max()) + { + return false; + } + ++n; + auto buf = std::make_unique<wchar_t[]>(n); + if (MsiGetPropertyW(handle, L"INSTALLLOCATION", buf.get(), &n) != ERROR_SUCCESS) + { + return false; + } + if (n != 0 && buf[n - 1] == L'\\') + { + --n; + } + installLocation->assign(buf.get(), n); + return true; +} + +typedef std::unique_ptr<void, decltype(&CloseHandle)> CloseHandleGuard; + +CloseHandleGuard guard(HANDLE handle) { return CloseHandleGuard(handle, CloseHandle); } + +bool runExecutable(std::wstring const& installLocation, wchar_t const* commandLine) +{ + STARTUPINFOW si{}; + si.cb = sizeof(si); + PROCESS_INFORMATION pi{}; + if (!CreateProcessW((installLocation + L"\\program\\update_service.exe").c_str(), + const_cast<LPWSTR>(commandLine), nullptr, nullptr, FALSE, CREATE_NO_WINDOW, + nullptr, nullptr, &si, &pi)) + { + return false; + } + auto const g(guard(pi.hProcess)); + DWORD res = WaitForSingleObject(pi.hProcess, INFINITE); + if (res != WAIT_OBJECT_0) + { + return false; + } + DWORD ec = 0; + if (!GetExitCodeProcess(pi.hProcess, &ec)) + { + return false; + } + if (ec != 0) + { + return false; + } + return true; +} +} + +extern "C" __declspec(dllexport) UINT __stdcall InstallUpdateservice(MSIHANDLE handle) +{ + std::wstring loc; + if (!getInstallLocation(handle, &loc)) + { + return false; + } + if (!runExecutable(loc, L"install")) + { + return ERROR_INVALID_FUNCTION; + } + WCHAR maintenanceServiceKey[MAX_PATH + 1]; + if (!CalculateRegistryPathFromFilePath(loc.c_str(), maintenanceServiceKey)) + { + return ERROR_INVALID_FUNCTION; + } + HKEY key; + if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, (std::wstring(maintenanceServiceKey) + L"\\0").c_str(), + 0, nullptr, REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_WOW64_64KEY, nullptr, + &key, nullptr) + != ERROR_SUCCESS) + { + return ERROR_INVALID_FUNCTION; + } + if (RegSetValueExW(key, L"issuer", 0, REG_SZ, + reinterpret_cast<BYTE const*>(L"Certum Code Signing 2021 CA"), + sizeof L"Certum Code Signing 2021 CA") + != ERROR_SUCCESS) + { + return ERROR_INVALID_FUNCTION; + } + if (RegSetValueExW(key, L"name", 0, REG_SZ, + reinterpret_cast<BYTE const*>(L"The Document Foundation"), + sizeof L"The Document Foundation") + != ERROR_SUCCESS) + { + return ERROR_INVALID_FUNCTION; + } + if (RegCloseKey(key) != ERROR_SUCCESS) + { + return ERROR_INVALID_FUNCTION; + } + return ERROR_SUCCESS; +} + +extern "C" __declspec(dllexport) UINT __stdcall UninstallUpdateservice(MSIHANDLE handle) +{ + std::wstring loc; + if (!getInstallLocation(handle, &loc)) + { + return false; + } + if (!runExecutable(loc, L"uninstall")) + { + return ERROR_INVALID_FUNCTION; + } + WCHAR maintenanceServiceKey[MAX_PATH + 1]; + if (!CalculateRegistryPathFromFilePath(loc.c_str(), maintenanceServiceKey)) + { + return ERROR_INVALID_FUNCTION; + } + if (RegDeleteTreeW(HKEY_LOCAL_MACHINE, maintenanceServiceKey) != ERROR_SUCCESS) + { + return ERROR_INVALID_FUNCTION; + } + return ERROR_SUCCESS; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/external/onlineupdate/install_updateservice.def b/external/onlineupdate/install_updateservice.def new file mode 100644 index 000000000000..a210387fce33 --- /dev/null +++ b/external/onlineupdate/install_updateservice.def @@ -0,0 +1,4 @@ +LIBRARY "install_updateservice.dll" +EXPORTS + InstallUpdateservice + UninstallUpdateservice diff --git a/scp2/source/ooo/windowscustomaction_ooo.scp b/scp2/source/ooo/windowscustomaction_ooo.scp index 41b78daad13b..0bd451c04f9d 100644 --- a/scp2/source/ooo/windowscustomaction_ooo.scp +++ b/scp2/source/ooo/windowscustomaction_ooo.scp @@ -16,6 +16,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include "config_features.h" #include "macros.inc" WindowsCustomAction gid_Customaction_Regallmsdocdll @@ -244,3 +245,25 @@ WindowsCustomAction gid_Customaction_prep_reg_dlls Inbinarytable = 1; Assignment1 = ("InstallExecuteSequence", "", "behind_CostFinalize"); End + +#if HAVE_FEATURE_UPDATE_MAR + +WindowsCustomAction gid_Customaction_install_updateservice + Name = "install_updateservice"; + Typ = "65"; + Source = "install_updateservice.dll"; + Target = "InstallUpdateservice"; + Inbinarytable = 1; + Assignment1 = ("InstallExecuteSequence", "Not REMOVE=\"ALL\"", "end"); +End + +WindowsCustomAction gid_Customaction_uninstall_updateservice + Name = "uninstall_updateservice"; + Typ = "65"; + Source = "install_updateservice.dll"; + Target = "UninstallUpdateservice"; + Inbinarytable = 1; + Assignment1 = ("InstallExecuteSequence", "REMOVE=\"ALL\"", "MigrateFeatureStates"); +End + +#endif |