/* -*- 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 #include #include #include #include #include #define WIN32_LEAN_AND_MEAN #include #include #include // 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(L""), &n) != ERROR_MORE_DATA || n == std::numeric_limits::max()) { return false; } ++n; auto buf = std::make_unique(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 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(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(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(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: */