diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
commit | 267c6f2ac71f92999e969232431ba04678e7437e (patch) | |
tree | 358c9467650e1d0a1d7227a21dac2e3d08b622b2 /external/onlineupdate/install_updateservice.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip |
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'external/onlineupdate/install_updateservice.cxx')
-rw-r--r-- | external/onlineupdate/install_updateservice.cxx | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/external/onlineupdate/install_updateservice.cxx b/external/onlineupdate/install_updateservice.cxx new file mode 100644 index 0000000000..c1d5471560 --- /dev/null +++ b/external/onlineupdate/install_updateservice.cxx @@ -0,0 +1,225 @@ +/* -*- 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 <algorithm> +#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 getProperty(MSIHANDLE handle, wchar_t const* name, std::wstring* value) +{ + DWORD n = 0; + if (MsiGetPropertyW(handle, name, 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, name, buf.get(), &n) != ERROR_SUCCESS) + { + return false; + } + if (n != 0 && buf[n - 1] == L'\\') + { + --n; + } + value->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* argument) +{ + std::wstring cmdline(L"\""); + cmdline += installLocation; + cmdline += L"\\program\\update_service.exe\" "; + cmdline += argument; + auto const n = cmdline.size() + 1; + auto const buf = std::make_unique<wchar_t[]>(n); + std::copy_n(cmdline.data(), n, buf.get()); + STARTUPINFOW si{}; + si.cb = sizeof(si); + PROCESS_INFORMATION pi{}; + if (!CreateProcessW(nullptr, buf.get(), 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; +} + +bool writeRegistry(std::wstring const& installLocation) +{ + WCHAR path[MAX_PATH + 1]; + if (!CalculateRegistryPathFromFilePath(installLocation.c_str(), path)) + { + return false; + } + HKEY key; + if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, (std::wstring(path) + L"\\0").c_str(), 0, nullptr, + REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_WOW64_64KEY, nullptr, &key, + nullptr) + != ERROR_SUCCESS) + { + return false; + } + auto ok = true; + 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) + { + ok = false; + } + if (RegSetValueExW(key, L"name", 0, REG_SZ, + reinterpret_cast<BYTE const*>(L"The Document Foundation"), + sizeof L"The Document Foundation") + != ERROR_SUCCESS) + { + ok = false; + } + if (RegCloseKey(key) != ERROR_SUCCESS) + { + ok = false; + } + return ok; +} + +bool deleteRegistry(std::wstring const& installLocation) +{ + WCHAR path[MAX_PATH + 1]; + if (!CalculateRegistryPathFromFilePath(installLocation.c_str(), path)) + { + return false; + } + if (RegDeleteTreeW(HKEY_LOCAL_MACHINE, path) != ERROR_SUCCESS) + { + return false; + } + return true; +} +} + +extern "C" __declspec(dllexport) UINT __stdcall PrepareUpdateservice(MSIHANDLE handle) +{ + std::wstring loc; + if (!getProperty(handle, L"INSTALLLOCATION", &loc)) + { + return ERROR_INSTALL_FAILURE; + } + auto ok = true; + if (MsiSetPropertyW(handle, L"install_updateservice", loc.c_str()) != ERROR_SUCCESS) + { + ok = false; + } + if (MsiSetPropertyW(handle, L"uninstall_updateservice", loc.c_str()) != ERROR_SUCCESS) + { + ok = false; + } + return ok ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; +} + +extern "C" __declspec(dllexport) UINT __stdcall InstallUpdateservice(MSIHANDLE handle) +{ + std::wstring loc; + if (!getProperty(handle, L"CustomActionData", &loc)) + { + return ERROR_INSTALL_FAILURE; + } + auto ok = true; + if (!runExecutable(loc, L"install")) + { + ok = false; + } + if (!writeRegistry(loc)) + { + ok = false; + } + return ok ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; +} + +extern "C" __declspec(dllexport) UINT __stdcall UninstallUpdateservice(MSIHANDLE handle) +{ + std::wstring loc; + if (!getProperty(handle, L"CustomActionData", &loc)) + { + return ERROR_INSTALL_FAILURE; + } + auto ok = true; + if (!runExecutable(loc, L"uninstall")) + { + ok = false; + } + if (!deleteRegistry(loc)) + { + ok = false; + } + return ok ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ |