tdf#81880 Search the Gallery
[LibreOffice.git] / external / onlineupdate / install_updateservice.cxx
blobc1d547156098a76e6ed24db775be390b18c6af8a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <sal/config.h>
12 #include <algorithm>
13 #include <cstddef>
14 #include <limits>
15 #include <memory>
16 #include <string>
18 #define WIN32_LEAN_AND_MEAN
19 #include <windows.h>
20 #include <msiquery.h>
22 #include <pathhash.h>
24 // Replacements for functions used in
25 // workdir/UnpackedTarball/onlineupdate/onlineupdate/source/update/common/pathhash.cpp but not
26 // available here:
28 extern "C" wchar_t* _wcslwr(wchar_t* str)
30 for (auto p = str; *p != L'\0'; ++p)
32 if (*p >= L'A' && *p <= L'Z')
34 *p += L'a' - L'A';
37 return str;
40 extern "C" wchar_t* wcsncpy(wchar_t* strDest, wchar_t const* strSource, std::size_t count)
42 for (std::size_t i = 0; i != count; ++i)
44 strDest[i] = *strSource;
45 if (*strSource != L'\0')
47 ++strSource;
50 return strDest;
53 namespace
55 bool getProperty(MSIHANDLE handle, wchar_t const* name, std::wstring* value)
57 DWORD n = 0;
58 if (MsiGetPropertyW(handle, name, const_cast<wchar_t*>(L""), &n) != ERROR_MORE_DATA
59 || n == std::numeric_limits<DWORD>::max())
61 return false;
63 ++n;
64 auto buf = std::make_unique<wchar_t[]>(n);
65 if (MsiGetPropertyW(handle, name, buf.get(), &n) != ERROR_SUCCESS)
67 return false;
69 if (n != 0 && buf[n - 1] == L'\\')
71 --n;
73 value->assign(buf.get(), n);
74 return true;
77 typedef std::unique_ptr<void, decltype(&CloseHandle)> CloseHandleGuard;
79 CloseHandleGuard guard(HANDLE handle) { return CloseHandleGuard(handle, CloseHandle); }
81 bool runExecutable(std::wstring const& installLocation, wchar_t const* argument)
83 std::wstring cmdline(L"\"");
84 cmdline += installLocation;
85 cmdline += L"\\program\\update_service.exe\" ";
86 cmdline += argument;
87 auto const n = cmdline.size() + 1;
88 auto const buf = std::make_unique<wchar_t[]>(n);
89 std::copy_n(cmdline.data(), n, buf.get());
90 STARTUPINFOW si{};
91 si.cb = sizeof(si);
92 PROCESS_INFORMATION pi{};
93 if (!CreateProcessW(nullptr, buf.get(), nullptr, nullptr, FALSE, CREATE_NO_WINDOW, nullptr,
94 nullptr, &si, &pi))
96 return false;
98 auto const g(guard(pi.hProcess));
99 DWORD res = WaitForSingleObject(pi.hProcess, INFINITE);
100 if (res != WAIT_OBJECT_0)
102 return false;
104 DWORD ec = 0;
105 if (!GetExitCodeProcess(pi.hProcess, &ec))
107 return false;
109 if (ec != 0)
111 return false;
113 return true;
116 bool writeRegistry(std::wstring const& installLocation)
118 WCHAR path[MAX_PATH + 1];
119 if (!CalculateRegistryPathFromFilePath(installLocation.c_str(), path))
121 return false;
123 HKEY key;
124 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, (std::wstring(path) + L"\\0").c_str(), 0, nullptr,
125 REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_WOW64_64KEY, nullptr, &key,
126 nullptr)
127 != ERROR_SUCCESS)
129 return false;
131 auto ok = true;
132 if (RegSetValueExW(key, L"issuer", 0, REG_SZ,
133 reinterpret_cast<BYTE const*>(L"Certum Code Signing 2021 CA"),
134 sizeof L"Certum Code Signing 2021 CA")
135 != ERROR_SUCCESS)
137 ok = false;
139 if (RegSetValueExW(key, L"name", 0, REG_SZ,
140 reinterpret_cast<BYTE const*>(L"The Document Foundation"),
141 sizeof L"The Document Foundation")
142 != ERROR_SUCCESS)
144 ok = false;
146 if (RegCloseKey(key) != ERROR_SUCCESS)
148 ok = false;
150 return ok;
153 bool deleteRegistry(std::wstring const& installLocation)
155 WCHAR path[MAX_PATH + 1];
156 if (!CalculateRegistryPathFromFilePath(installLocation.c_str(), path))
158 return false;
160 if (RegDeleteTreeW(HKEY_LOCAL_MACHINE, path) != ERROR_SUCCESS)
162 return false;
164 return true;
168 extern "C" __declspec(dllexport) UINT __stdcall PrepareUpdateservice(MSIHANDLE handle)
170 std::wstring loc;
171 if (!getProperty(handle, L"INSTALLLOCATION", &loc))
173 return ERROR_INSTALL_FAILURE;
175 auto ok = true;
176 if (MsiSetPropertyW(handle, L"install_updateservice", loc.c_str()) != ERROR_SUCCESS)
178 ok = false;
180 if (MsiSetPropertyW(handle, L"uninstall_updateservice", loc.c_str()) != ERROR_SUCCESS)
182 ok = false;
184 return ok ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
187 extern "C" __declspec(dllexport) UINT __stdcall InstallUpdateservice(MSIHANDLE handle)
189 std::wstring loc;
190 if (!getProperty(handle, L"CustomActionData", &loc))
192 return ERROR_INSTALL_FAILURE;
194 auto ok = true;
195 if (!runExecutable(loc, L"install"))
197 ok = false;
199 if (!writeRegistry(loc))
201 ok = false;
203 return ok ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
206 extern "C" __declspec(dllexport) UINT __stdcall UninstallUpdateservice(MSIHANDLE handle)
208 std::wstring loc;
209 if (!getProperty(handle, L"CustomActionData", &loc))
211 return ERROR_INSTALL_FAILURE;
213 auto ok = true;
214 if (!runExecutable(loc, L"uninstall"))
216 ok = false;
218 if (!deleteRegistry(loc))
220 ok = false;
222 return ok ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
225 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */