@samitouri / QOSAMI-WSL / commits / d7ff5b96

Refactor: trim unnecessary DLL deps from COMMON_LINK_LIBRARIES (#14426)

* Refactor: trim unnecessary DLL deps from COMMON_LINK_LIBRARIES - Split MSI/Wintrust install functions from wslutil.cpp into install.cpp - Remove MI.lib, wsldeps.lib, msi.lib, Wintrust.lib, computecore.lib, computenetwork.lib, Iphlpapi.lib from COMMON_LINK_LIBRARIES - Add per-target MSI_LINK_LIBRARIES, HCS_LINK_LIBRARIES, SERVICE_LINK_LIBRARIES - Delay-load msi.dll and WINTRUST.dll for wsl.exe and wslg.exe - Result: wslhost, wslrelay, wslcsdk, testplugin lose msi/wintrust startup imports; wsl.exe and wslg.exe defer msi/wintrust loading until actually needed; wslservice is the only target that imports computecore/computenetwork/Iphlpapi * minor fixes to install.cpp that were caught during PR * move to wsl::windows::common::install namespace --------- Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>

Ben Hillis committed Mar 19, 2026 at 12:45 UTC d7ff5b96315a6cd710d1044702182db99a1e2cb9
17 files changed +531 -433
CMakeLists.txt
+10 -4
@@ -250,13 +250,19 @@ set(COMMON_LINK_LIBRARIES
250 Shlwapi.lib
251 synchronization.lib
252 Bcrypt.lib
253 - Iphlpapi.lib
254 - icu.lib
253 + icu.lib)
254 +
255 +set(MSI_LINK_LIBRARIES
256 + Wintrust.lib
257 + msi.lib)
258 +
259 +set(HCS_LINK_LIBRARIES
260 computecore.lib
261 computenetwork.lib
262 + Iphlpapi.lib)
263 +
264 +set(SERVICE_LINK_LIBRARIES
265 MI.lib
258 - Wintrust.lib
259 - msi.lib
266 wsldeps.lib)
267
268 # Linux
src/windows/common/CMakeLists.txt
+1
@@ -45,6 +45,7 @@ set(SOURCES
45 WslTelemetry.cpp
46 VirtioNetworking.cpp
47 wslutil.cpp
48 + install.cpp
49 notifications.cpp)
50
51 set(HEADERS
src/windows/common/WslClient.cpp
+6 -5
@@ -13,6 +13,7 @@ Abstract:
13 --*/
14
15 #include "precomp.h"
16 +#include "install.h"
17 #include "WslInstall.h"
18 #include "HandleConsoleProgressBar.h"
19 #include "Distribution.h"
@@ -156,7 +157,7 @@ int BashMain(_In_ std::wstring_view commandLine)
157 // Call the MSI package if we're in an MSIX context
158 if (wsl::windows::common::wslutil::IsRunningInMsix())
159 {
159 - return wsl::windows::common::wslutil::CallMsiPackage();
160 + return wsl::windows::common::install::CallMsiPackage();
161 }
162
163 const auto options = ParseLegacyArguments(commandLine);
@@ -1265,7 +1266,7 @@ int UpdatePackage(std::wstring_view commandLine)
1266 parser.AddArgument(NoOp(), WSL_UPDATE_ARG_PROMPT_OPTION_LONG);
1267 parser.Parse();
1268
1268 - return wsl::windows::common::wslutil::UpdatePackage(preRelease, false);
1269 + return wsl::windows::common::install::UpdatePackage(preRelease, false);
1270 }
1271
1272 int Uninstall()
@@ -1274,7 +1275,7 @@ int Uninstall()
1275 auto clearLogs =
1276 wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&logFile]() { LOG_IF_WIN32_BOOL_FALSE(DeleteFile(logFile.c_str())); });
1277
1277 - const auto exitCode = wsl::windows::common::wslutil::UninstallViaMsi(logFile.c_str(), &wsl::windows::common::wslutil::MsiMessageCallback);
1278 + const auto exitCode = wsl::windows::common::install::UninstallViaMsi(logFile.c_str(), &wsl::windows::common::install::MsiMessageCallback);
1279
1280 if (exitCode != 0)
1281 {
@@ -1311,7 +1312,7 @@ int WslconfigMain(_In_ int argc, _In_reads_(argc) LPWSTR* argv)
1312 // Call the MSI package if we're in an MSIX context
1313 if (wsl::windows::common::wslutil::IsRunningInMsix())
1314 {
1314 - return wsl::windows::common::wslutil::CallMsiPackage();
1315 + return wsl::windows::common::install::CallMsiPackage();
1316 }
1317
1318 using wsl::shared::string::IsEqual;
@@ -1524,7 +1525,7 @@ int WslMain(_In_ std::wstring_view commandLine)
1525 // Call the MSI package if we're in an MSIX context
1526 if (wsl::windows::common::wslutil::IsRunningInMsix())
1527 {
1527 - return wsl::windows::common::wslutil::CallMsiPackage();
1528 + return wsl::windows::common::install::CallMsiPackage();
1529 }
1530
1531 // Use exit code -1 so invokers of wsl.exe can distinguish between a Linux
src/windows/common/install.cpp new
+455
@@ -0,0 +1,455 @@
1 +/*++
2 +
3 +Copyright (c) Microsoft. All rights reserved.
4 +
5 +Module Name:
6 +
7 + install.cpp
8 +
9 +Abstract:
10 +
11 + This file contains MSI/Wintrust install helper functions.
12 + Split from wslutil.cpp to avoid pulling msi.dll/wintrust.dll
13 + into targets that don't need them.
14 +
15 +--*/
16 +
17 +#include "precomp.h"
18 +#include "install.h"
19 +#include "wslutil.h"
20 +#include "WslPluginApi.h"
21 +#include "wslinstallerservice.h"
22 +
23 +#include "ConsoleProgressBar.h"
24 +#include "ExecutionContext.h"
25 +#include "MsiQuery.h"
26 +
27 +using winrt::Windows::Foundation::Uri;
28 +using winrt::Windows::Management::Deployment::DeploymentOptions;
29 +using wsl::shared::Localization;
30 +using wsl::windows::common::Context;
31 +using namespace wsl::windows::common::registry;
32 +using namespace wsl::windows::common::wslutil;
33 +using namespace wsl::windows::common::install;
34 +
35 +namespace {
36 +
37 +bool PromptForKeyPress()
38 +{
39 + THROW_IF_WIN32_BOOL_FALSE(FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE)));
40 +
41 + // Note: Ctrl-c causes _getch to return 0x3.
42 + return _getch() != 0x3;
43 +}
44 +
45 +bool PromptForKeyPressWithTimeout()
46 +{
47 + // Run PromptForKeyPress on a separate thread so we can apply a timeout.
48 + // If PromptForKeyPress fails, fulfill the promise with false so the caller doesn't hang.
49 + std::promise<bool> pressedKey;
50 + auto thread = std::thread([&pressedKey]() {
51 + try
52 + {
53 + pressedKey.set_value(PromptForKeyPress());
54 + }
55 + catch (...)
56 + {
57 + LOG_CAUGHT_EXCEPTION();
58 + try
59 + {
60 + pressedKey.set_value(false);
61 + }
62 + CATCH_LOG()
63 + }
64 + });
65 +
66 + auto cancelRead = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&thread]() {
67 + if (thread.joinable())
68 + {
69 + LOG_IF_WIN32_BOOL_FALSE(CancelSynchronousIo(thread.native_handle()));
70 + thread.join();
71 + }
72 + });
73 +
74 + auto future = pressedKey.get_future();
75 + const auto waitResult = future.wait_for(std::chrono::minutes(1));
76 +
77 + return waitResult == std::future_status::ready && future.get();
78 +}
79 +
80 +int UpdatePackageImpl(bool preRelease, bool repair)
81 +{
82 + if (!repair)
83 + {
84 + PrintMessage(Localization::MessageCheckingForUpdates());
85 + }
86 +
87 + auto [version, release] = GetLatestGitHubRelease(preRelease);
88 +
89 + if (!repair && ParseWslPackageVersion(version) <= wsl::shared::PackageVersion)
90 + {
91 + PrintMessage(Localization::MessageUpdateNotNeeded());
92 + return 0;
93 + }
94 +
95 + PrintMessage(Localization::MessageUpdatingToVersion(version.c_str()));
96 +
97 + const bool msiInstall = wsl::shared::string::EndsWith<wchar_t>(release.name, L".msi");
98 + const auto downloadPath = DownloadFile(release.url, release.name);
99 + if (msiInstall)
100 + {
101 + auto logFile = std::filesystem::temp_directory_path() / L"wsl-install-logs.txt";
102 + auto clearLogs =
103 + wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&logFile]() { LOG_IF_WIN32_BOOL_FALSE(DeleteFile(logFile.c_str())); });
104 +
105 + const auto exitCode = UpgradeViaMsi(downloadPath.c_str(), L"", logFile.c_str(), &MsiMessageCallback);
106 +
107 + if (exitCode != 0)
108 + {
109 + clearLogs.release();
110 + THROW_HR_WITH_USER_ERROR(
111 + HRESULT_FROM_WIN32(exitCode),
112 + wsl::shared::Localization::MessageUpdateFailed(exitCode) + L"\r\n" +
113 + wsl::shared::Localization::MessageSeeLogFile(logFile.c_str()));
114 + }
115 + }
116 + else
117 + {
118 + // Set FILE_FLAG_DELETE_ON_CLOSE on the file to make sure it's deleted when the installation completes.
119 + const wil::unique_hfile package{CreateFileW(
120 + downloadPath.c_str(), DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, nullptr)};
121 +
122 + THROW_LAST_ERROR_IF(!package);
123 +
124 + const winrt::Windows::Management::Deployment::PackageManager packageManager;
125 + const auto result = packageManager.AddPackageAsync(
126 + Uri{downloadPath.c_str()}, nullptr, DeploymentOptions::ForceApplicationShutdown | DeploymentOptions::ForceTargetApplicationShutdown);
127 +
128 + THROW_IF_FAILED(result.get().ExtendedErrorCode());
129 +
130 + // Note: If the installation is successful, this process is expected to receive and Ctrl-C and exit
131 + }
132 +
133 + return 0;
134 +}
135 +
136 +void WaitForMsiInstall()
137 +{
138 + wil::com_ptr_t<IWslInstaller> installer;
139 +
140 + auto retry_pred = []() {
141 + const auto errorCode = wil::ResultFromCaughtException();
142 + return errorCode == REGDB_E_CLASSNOTREG;
143 + };
144 +
145 + wsl::shared::retry::RetryWithTimeout<void>(
146 + [&installer]() { installer = wil::CoCreateInstance<IWslInstaller>(__uuidof(WslInstaller), CLSCTX_LOCAL_SERVER); },
147 + std::chrono::seconds(1),
148 + std::chrono::minutes(1),
149 + retry_pred);
150 +
151 + fputws(wsl::shared::Localization::MessageFinishMsiInstallation().c_str(), stderr);
152 +
153 + auto finishLine = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, []() { fputws(L"\n", stderr); });
154 +
155 + UINT exitCode = -1;
156 + wil::unique_cotaskmem_string message{};
157 + THROW_IF_FAILED(installer->Install(&exitCode, &message));
158 +
159 + if (message && *message.get() != UNICODE_NULL)
160 + {
161 + finishLine.release();
162 + wprintf(L"\n%ls\n", message.get());
163 + }
164 +
165 + if (exitCode != 0)
166 + {
167 + THROW_HR_WITH_USER_ERROR(HRESULT_FROM_WIN32(exitCode), wsl::shared::Localization::MessageUpdateFailed(exitCode));
168 + }
169 +}
170 +
171 +wil::unique_handle CreateJob()
172 +{
173 + // Create a job object that will terminate all processes in the job on
174 + // close but will not terminate the children of the processes in the job.
175 + // This is used to ensure that when forwarding from an inbox binary (I)
176 + // to a lifted binary (L), if I is terminated L is terminated as well but
177 + // any children of L (e.g. wslhost.exe) continue to run.
178 + wil::unique_handle job{CreateJobObject(nullptr, nullptr)};
179 + THROW_LAST_ERROR_IF_NULL(job.get());
180 +
181 + JOBOBJECT_EXTENDED_LIMIT_INFORMATION info{};
182 + info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK;
183 + THROW_IF_WIN32_BOOL_FALSE(SetInformationJobObject(job.get(), JobObjectExtendedLimitInformation, &info, sizeof(info)));
184 +
185 + return job;
186 +}
187 +
188 +int WINAPI InstallRecordHandler(void* context, UINT messageType, LPCWSTR message)
189 +{
190 + try
191 + {
192 + WSL_LOG("MSIMessage", TraceLoggingValue(messageType, "type"), TraceLoggingValue(message, "message"));
193 + auto type = (INSTALLMESSAGE)(0xFF000000 & (UINT)messageType);
194 +
195 + if (type == INSTALLMESSAGE_ERROR || type == INSTALLMESSAGE_FATALEXIT || type == INSTALLMESSAGE_WARNING)
196 + {
197 + WriteInstallLog(std::format("MSI message: {}", message));
198 + }
199 +
200 + auto* callback = reinterpret_cast<const std::function<void(INSTALLMESSAGE, LPCWSTR)>*>(context);
201 + if (callback != nullptr)
202 + {
203 + (*callback)(type, message);
204 + }
205 + }
206 + CATCH_LOG();
207 +
208 + return IDOK;
209 +}
210 +
211 +void ConfigureMsiLogging(_In_opt_ LPCWSTR LogFile, _In_ const std::function<void(INSTALLMESSAGE, LPCWSTR)>& Callback)
212 +{
213 + if (LogFile != nullptr)
214 + {
215 + LOG_IF_WIN32_ERROR(MsiEnableLog(INSTALLLOGMODE_VERBOSE | INSTALLLOGMODE_EXTRADEBUG | INSTALLLOGMODE_PROGRESS, LogFile, 0));
216 + }
217 +
218 + MsiSetExternalUI(
219 + &InstallRecordHandler,
220 + INSTALLLOGMODE_FATALEXIT | INSTALLLOGMODE_ERROR | INSTALLLOGMODE_WARNING | INSTALLLOGMODE_USER | INSTALLLOGMODE_INFO |
221 + INSTALLLOGMODE_RESOLVESOURCE | INSTALLLOGMODE_OUTOFDISKSPACE | INSTALLLOGMODE_ACTIONSTART | INSTALLLOGMODE_ACTIONDATA |
222 + INSTALLLOGMODE_COMMONDATA | INSTALLLOGMODE_INITIALIZE | INSTALLLOGMODE_TERMINATE | INSTALLLOGMODE_SHOWDIALOG,
223 + (void*)&Callback);
224 +
225 + MsiSetInternalUI(INSTALLUILEVEL(INSTALLUILEVEL_NONE | INSTALLUILEVEL_UACONLY | INSTALLUILEVEL_SOURCERESONLY), nullptr);
226 +}
227 +
228 +} // namespace
229 +
230 +int wsl::windows::common::install::CallMsiPackage()
231 +{
232 + wsl::windows::common::ExecutionContext context(wsl::windows::common::CallMsi);
233 +
234 + auto msiPath = GetMsiPackagePath();
235 + if (!msiPath.has_value())
236 + {
237 + wsl::windows::common::ExecutionContext context(wsl::windows::common::Install);
238 +
239 + try
240 + {
241 + WaitForMsiInstall();
242 + msiPath = GetMsiPackagePath();
243 + }
244 + catch (...)
245 + {
246 + LOG_CAUGHT_EXCEPTION();
247 +
248 + // GetMsiPackagePath() will generate a user error if the registry access fails.
249 + // Save the error from GetMsiPackagePath() to return a proper 'install failed' message.
250 + auto savedError = context.ReportedError();
251 +
252 + // There is a race where the service might stop before returning the install result.
253 + // if this happens, only fail if the MSI still isn't installed.
254 + msiPath = GetMsiPackagePath();
255 + if (!msiPath.has_value())
256 + {
257 + // Offer to directly install the MSI package if the MsixInstaller logic fails
258 + // This can trigger a UAC so only do it
259 + if (IsInteractiveConsole())
260 + {
261 + auto errorCode = savedError.has_value() ? ErrorToString(savedError.value()).Code
262 + : ErrorCodeToString(wil::ResultFromCaughtException());
263 +
264 + EMIT_USER_WARNING(wsl::shared::Localization::MessageInstallationCorrupted(errorCode));
265 +
266 + if (PromptForKeyPressWithTimeout())
267 + {
268 + return UpdatePackage(false, true);
269 + }
270 + }
271 +
272 + if (savedError.has_value())
273 + {
274 + THROW_HR_WITH_USER_ERROR(savedError->Code, savedError->Message.value_or(L""));
275 + }
276 +
277 + throw;
278 + }
279 + }
280 +
281 + THROW_HR_IF(E_UNEXPECTED, !msiPath.has_value());
282 + }
283 +
284 + auto target = msiPath.value() + L"\\" WSL_BINARY_NAME;
285 +
286 + SubProcess process(target.c_str(), GetCommandLine());
287 + process.SetDesktopAppPolicy(PROCESS_CREATION_DESKTOP_APP_BREAKAWAY_ENABLE_PROCESS_TREE);
288 + auto runningProcess = process.Start();
289 +
290 + // N.B. The job cannot be assigned at process creation time as the packaged process
291 + // creation path will assign the new process to a per package job object.
292 + // In the case of multiple processes running in a single package, assigning
293 + // the new process to the per package job object will fail for the second request
294 + // since both jobs already have processes which prevents a job hierarchy from
295 + // being established.
296 + auto job = CreateJob();
297 +
298 + // Assign the process to the job, ignoring failures when the process has
299 + // terminated.
300 + //
301 + // N.B. Assigning the job after process creation without CREATE_SUSPENDED is
302 + // safe to do here since only the new child process will be in the job
303 + // object. None of the grandchildren processes are included since the
304 + // job is created with JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK.
305 + if (!AssignProcessToJobObject(job.get(), runningProcess.get()))
306 + {
307 + auto lastError = GetLastError();
308 + if (lastError != ERROR_ACCESS_DENIED)
309 + {
310 + THROW_WIN32(lastError);
311 + }
312 + }
313 +
314 + return static_cast<int>(SubProcess::GetExitCode(runningProcess.get()));
315 +}
316 +
317 +void wsl::windows::common::install::MsiMessageCallback(INSTALLMESSAGE type, LPCWSTR message)
318 +{
319 + switch (type)
320 + {
321 + case INSTALLMESSAGE_ERROR:
322 + case INSTALLMESSAGE_FATALEXIT:
323 + case INSTALLMESSAGE_WARNING:
324 + wprintf(L"%ls\n", message);
325 + break;
326 +
327 + default:
328 + break;
329 + }
330 +}
331 +
332 +int wsl::windows::common::install::UpdatePackage(bool PreRelease, bool Repair)
333 +{
334 + // Register a console control handler so "^C" is not printed when the app platform terminates the process.
335 + THROW_IF_WIN32_BOOL_FALSE(SetConsoleCtrlHandler(
336 + [](DWORD ctrlType) {
337 + if (ctrlType == CTRL_C_EVENT)
338 + {
339 + ExitProcess(0);
340 + }
341 + return FALSE;
342 + },
343 + TRUE));
344 +
345 + auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [] { SetConsoleCtrlHandler(nullptr, FALSE); });
346 +
347 + try
348 + {
349 + return UpdatePackageImpl(PreRelease, Repair);
350 + }
351 + catch (...)
352 + {
353 + // Rethrowing via WIL is required for the error context to be properly set in case a winrt exception was thrown.
354 + THROW_HR(wil::ResultFromCaughtException());
355 + }
356 +}
357 +
358 +UINT wsl::windows::common::install::UpgradeViaMsi(
359 + _In_ LPCWSTR PackageLocation, _In_opt_ LPCWSTR ExtraArgs, _In_opt_ LPCWSTR LogFile, _In_ const std::function<void(INSTALLMESSAGE, LPCWSTR)>& Callback)
360 +{
361 + WriteInstallLog(std::format("Upgrading via MSI package: {}. Args: {}", PackageLocation, ExtraArgs != nullptr ? ExtraArgs : L""));
362 +
363 + ConfigureMsiLogging(LogFile, Callback);
364 +
365 + auto result = MsiInstallProduct(PackageLocation, ExtraArgs);
366 + WSL_LOG(
367 + "MsiInstallResult",
368 + TraceLoggingValue(result, "result"),
369 + TraceLoggingValue(ExtraArgs != nullptr ? ExtraArgs : L"", "ExtraArgs"));
370 +
371 + WriteInstallLog(std::format("MSI upgrade result: {}", result));
372 +
373 + return result;
374 +}
375 +
376 +UINT wsl::windows::common::install::UninstallViaMsi(_In_opt_ LPCWSTR LogFile, _In_ const std::function<void(INSTALLMESSAGE, LPCWSTR)>& Callback)
377 +{
378 + const auto key = OpenLxssMachineKey(KEY_READ);
379 + const auto productCode = ReadString(key.get(), L"Msi", L"ProductCode", nullptr);
380 +
381 + WriteInstallLog(std::format("Uninstalling MSI package: {}", productCode));
382 +
383 + ConfigureMsiLogging(LogFile, Callback);
384 +
385 + auto result = MsiConfigureProduct(productCode.c_str(), 0, INSTALLSTATE_ABSENT);
386 + WSL_LOG("MsiUninstallResult", TraceLoggingValue(result, "result"));
387 +
388 + WriteInstallLog(std::format("MSI package uninstall result: {}", result));
389 +
390 + return result;
391 +}
392 +
393 +wil::unique_hfile wsl::windows::common::install::ValidateFileSignature(LPCWSTR Path)
394 +{
395 + wil::unique_hfile fileHandle{CreateFileW(Path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr)};
396 + THROW_LAST_ERROR_IF(!fileHandle);
397 +
398 + GUID action = WINTRUST_ACTION_GENERIC_VERIFY_V2;
399 + WINTRUST_DATA trust{};
400 + trust.cbStruct = sizeof(trust);
401 + trust.dwUIChoice = WTD_UI_NONE;
402 + trust.dwUnionChoice = WTD_CHOICE_FILE;
403 + trust.dwStateAction = WTD_STATEACTION_VERIFY;
404 +
405 + WINTRUST_FILE_INFO file = {0};
406 + file.cbStruct = sizeof(file);
407 + file.hFile = fileHandle.get();
408 + trust.pFile = &file;
409 +
410 + auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&]() {
411 + trust.dwStateAction = WTD_STATEACTION_CLOSE;
412 + WinVerifyTrust(nullptr, &action, &trust);
413 + });
414 +
415 + THROW_IF_WIN32_ERROR(WinVerifyTrust(nullptr, &action, &trust));
416 +
417 + return fileHandle;
418 +}
419 +
420 +void wsl::windows::common::install::WriteInstallLog(const std::string& Content)
421 +try
422 +{
423 + static std::wstring path = wil::GetWindowsDirectoryW<std::wstring>() + L"\\temp\\wsl-install-log.txt";
424 +
425 + // Wait up to 10 seconds for the log file mutex
426 + wil::unique_handle mutex{CreateMutex(nullptr, true, L"Global\\WslInstallLog")};
427 + THROW_LAST_ERROR_IF(!mutex);
428 +
429 + THROW_LAST_ERROR_IF(WaitForSingleObject(mutex.get(), 10 * 1000) != WAIT_OBJECT_0);
430 +
431 + wil::unique_handle file{CreateFile(
432 + path.c_str(), GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_ALWAYS, 0, nullptr)};
433 +
434 + THROW_LAST_ERROR_IF(!file);
435 +
436 + LARGE_INTEGER size{};
437 + THROW_IF_WIN32_BOOL_FALSE(GetFileSizeEx(file.get(), &size));
438 +
439 + // Append to the file if its size is below 10MB, otherwise truncate.
440 + if (size.QuadPart < 10 * _1MB)
441 + {
442 + THROW_LAST_ERROR_IF(SetFilePointer(file.get(), 0, nullptr, FILE_END) == INVALID_SET_FILE_POINTER);
443 + }
444 + else
445 + {
446 + THROW_IF_WIN32_BOOL_FALSE(SetEndOfFile(file.get()));
447 + }
448 +
449 + static auto processName = wil::GetModuleFileNameW<std::wstring>();
450 + auto logLine = std::format("{:%FT%TZ} {}[{}]: {}\n", std::chrono::system_clock::now(), processName, WSL_PACKAGE_VERSION, Content);
451 +
452 + DWORD bytesWritten{};
453 + THROW_IF_WIN32_BOOL_FALSE(WriteFile(file.get(), logLine.c_str(), static_cast<DWORD>(logLine.size()), &bytesWritten, nullptr));
454 +}
455 +CATCH_LOG();
src/windows/common/install.h new
+34
@@ -0,0 +1,34 @@
1 +/*++
2 +
3 +Copyright (c) Microsoft. All rights reserved.
4 +
5 +Module Name:
6 +
7 + install.h
8 +
9 +Abstract:
10 +
11 + This file contains MSI/Wintrust install helper function declarations.
12 +
13 +--*/
14 +
15 +#pragma once
16 +#include <functional>
17 +
18 +namespace wsl::windows::common::install {
19 +
20 +int CallMsiPackage();
21 +
22 +void MsiMessageCallback(INSTALLMESSAGE type, LPCWSTR message);
23 +
24 +wil::unique_hfile ValidateFileSignature(LPCWSTR Path);
25 +
26 +int UpdatePackage(bool PreRelease, bool Repair);
27 +
28 +UINT UpgradeViaMsi(_In_ LPCWSTR PackageLocation, _In_opt_ LPCWSTR ExtraArgs, _In_opt_ LPCWSTR LogFile, _In_ const std::function<void(INSTALLMESSAGE, LPCWSTR)>& callback);
29 +
30 +UINT UninstallViaMsi(_In_opt_ LPCWSTR LogFile, _In_ const std::function<void(INSTALLMESSAGE, LPCWSTR)>& callback);
31 +
32 +void WriteInstallLog(const std::string& Content);
33 +
34 +} // namespace wsl::windows::common::install
src/windows/common/wslutil.cpp
-402
@@ -216,141 +216,6 @@ bool IsWinInetError(HRESULT error)
216 return code >= INTERNET_ERROR_BASE && code <= INTERNET_ERROR_LAST;
217 }
218
219 -bool PromptForKeyPress()
220 -{
221 - THROW_IF_WIN32_BOOL_FALSE(FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE)));
222 -
223 - // Note: Ctrl-c causes _getch to return 0x3.
224 - return _getch() != 0x3;
225 -}
226 -
227 -bool PromptForKeyPressWithTimeout()
228 -{
229 - std::promise<bool> pressedKey;
230 - auto thread = std::thread([&pressedKey]() { pressedKey.set_value(PromptForKeyPress()); });
231 -
232 - auto cancelRead = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&thread]() {
233 - if (thread.joinable())
234 - {
235 - LOG_IF_WIN32_BOOL_FALSE(CancelSynchronousIo(thread.native_handle()));
236 - thread.join();
237 - }
238 - });
239 -
240 - auto future = pressedKey.get_future();
241 - const auto waitResult = future.wait_for(std::chrono::minutes(1));
242 -
243 - return waitResult == std::future_status::ready && future.get();
244 -}
245 -
246 -int UpdatePackageImpl(bool preRelease, bool repair)
247 -{
248 - if (!repair)
249 - {
250 - PrintMessage(Localization::MessageCheckingForUpdates());
251 - }
252 -
253 - auto [version, release] = GetLatestGitHubRelease(preRelease);
254 -
255 - if (!repair && ParseWslPackageVersion(version) <= wsl::shared::PackageVersion)
256 - {
257 - PrintMessage(Localization::MessageUpdateNotNeeded());
258 - return 0;
259 - }
260 -
261 - PrintMessage(Localization::MessageUpdatingToVersion(version.c_str()));
262 -
263 - const bool msiInstall = wsl::shared::string::EndsWith<wchar_t>(release.name, L".msi");
264 - const auto downloadPath = DownloadFile(release.url, release.name);
265 - if (msiInstall)
266 - {
267 - auto logFile = std::filesystem::temp_directory_path() / L"wsl-install-logs.txt";
268 - auto clearLogs =
269 - wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&logFile]() { LOG_IF_WIN32_BOOL_FALSE(DeleteFile(logFile.c_str())); });
270 -
271 - const auto exitCode = UpgradeViaMsi(downloadPath.c_str(), L"", logFile.c_str(), &MsiMessageCallback);
272 -
273 - if (exitCode != 0)
274 - {
275 - clearLogs.release();
276 - THROW_HR_WITH_USER_ERROR(
277 - HRESULT_FROM_WIN32(exitCode),
278 - wsl::shared::Localization::MessageUpdateFailed(exitCode) + L"\r\n" +
279 - wsl::shared::Localization::MessageSeeLogFile(logFile.c_str()));
280 - }
281 - }
282 - else
283 - {
284 - // Set FILE_FLAG_DELETE_ON_CLOSE on the file to make sure it's deleted when the installation completes.
285 - const wil::unique_hfile package{CreateFileW(
286 - downloadPath.c_str(), DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, nullptr)};
287 -
288 - THROW_LAST_ERROR_IF(!package);
289 -
290 - const winrt::Windows::Management::Deployment::PackageManager packageManager;
291 - const auto result = packageManager.AddPackageAsync(
292 - Uri{downloadPath.c_str()}, nullptr, DeploymentOptions::ForceApplicationShutdown | DeploymentOptions::ForceTargetApplicationShutdown);
293 -
294 - THROW_IF_FAILED(result.get().ExtendedErrorCode());
295 -
296 - // Note: If the installation is successful, this process is expected to receive and Ctrl-C and exit
297 - }
298 -
299 - return 0;
300 -}
301 -
302 -void WaitForMsiInstall()
303 -{
304 - wil::com_ptr_t<IWslInstaller> installer;
305 -
306 - auto retry_pred = []() {
307 - const auto errorCode = wil::ResultFromCaughtException();
308 - return errorCode == REGDB_E_CLASSNOTREG;
309 - };
310 -
311 - wsl::shared::retry::RetryWithTimeout<void>(
312 - [&installer]() { installer = wil::CoCreateInstance<IWslInstaller>(__uuidof(WslInstaller), CLSCTX_LOCAL_SERVER); },
313 - std::chrono::seconds(1),
314 - std::chrono::minutes(1),
315 - retry_pred);
316 -
317 - fputws(wsl::shared::Localization::MessageFinishMsiInstallation().c_str(), stderr);
318 -
319 - auto finishLine = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, []() { fputws(L"\n", stderr); });
320 -
321 - UINT exitCode = -1;
322 - wil::unique_cotaskmem_string message = nullptr;
323 - THROW_IF_FAILED(installer->Install(&exitCode, &message));
324 -
325 - if (*message.get() != UNICODE_NULL)
326 - {
327 - finishLine.release();
328 - wprintf(L"\n%ls\n", message.get());
329 - }
330 -
331 - if (exitCode != 0)
332 - {
333 - THROW_HR_WITH_USER_ERROR(HRESULT_FROM_WIN32(exitCode), wsl::shared::Localization::MessageUpdateFailed(exitCode));
334 - }
335 -}
336 -
337 -wil::unique_handle CreateJob()
338 -{
339 - // Create a job object that will terminate all processes in the job on
340 - // close but will not terminate the children of the processes in the job.
341 - // This is used to ensure that when forwarding from an inbox binary (I)
342 - // to a lifted binary (L), if I is terminated L is terminated as well but
343 - // any children of L (e.g. wslhost.exe) continue to run.
344 - wil::unique_handle job{CreateJobObject(nullptr, nullptr)};
345 - THROW_LAST_ERROR_IF_NULL(job.get());
346 -
347 - JOBOBJECT_EXTENDED_LIMIT_INFORMATION info{};
348 - info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK;
349 - THROW_IF_WIN32_BOOL_FALSE(SetInformationJobObject(job.get(), JobObjectExtendedLimitInformation, &info, sizeof(info)));
350 -
351 - return job;
352 -}
353 -
219 constexpr uint16_t EndianSwap(uint16_t value)
220 {
221 return (value & 0xFF00) >> 8 | (value & 0x00FF) << 8;
@@ -376,93 +241,6 @@ constexpr GUID EndianSwap(GUID value)
241
242 } // namespace
243
379 -int wsl::windows::common::wslutil::CallMsiPackage()
380 -{
381 - wsl::windows::common::ExecutionContext context(wsl::windows::common::CallMsi);
382 -
383 - auto msiPath = GetMsiPackagePath();
384 - if (!msiPath.has_value())
385 - {
386 - wsl::windows::common::ExecutionContext context(wsl::windows::common::Install);
387 -
388 - try
389 - {
390 - WaitForMsiInstall();
391 - msiPath = GetMsiPackagePath();
392 - }
393 - catch (...)
394 - {
395 - LOG_CAUGHT_EXCEPTION();
396 -
397 - // GetMsiPackagePath() will generate a user error if the registry access fails.
398 - // Save the error from GetMsiPackagePath() to return a proper 'install failed' message.
399 - auto savedError = context.ReportedError();
400 -
401 - // There is a race where the service might stop before returning the install result.
402 - // if this happens, only fail if the MSI still isn't installed.
403 - msiPath = GetMsiPackagePath();
404 - if (!msiPath.has_value())
405 - {
406 - // Offer to directly install the MSI package if the MsixInstaller logic fails
407 - // This can trigger a UAC so only do it
408 - if (IsInteractiveConsole())
409 - {
410 - auto errorCode = savedError.has_value() ? ErrorToString(savedError.value()).Code
411 - : ErrorCodeToString(wil::ResultFromCaughtException());
412 -
413 - EMIT_USER_WARNING(wsl::shared::Localization::MessageInstallationCorrupted(errorCode));
414 -
415 - if (PromptForKeyPressWithTimeout())
416 - {
417 - return UpdatePackage(false, true);
418 - }
419 - }
420 -
421 - if (savedError.has_value())
422 - {
423 - THROW_HR_WITH_USER_ERROR(savedError->Code, savedError->Message.value_or(L""));
424 - }
425 -
426 - throw;
427 - }
428 - }
429 -
430 - THROW_HR_IF(E_UNEXPECTED, !msiPath.has_value());
431 - }
432 -
433 - auto target = msiPath.value() + L"\\" WSL_BINARY_NAME;
434 -
435 - SubProcess process(target.c_str(), GetCommandLine());
436 - process.SetDesktopAppPolicy(PROCESS_CREATION_DESKTOP_APP_BREAKAWAY_ENABLE_PROCESS_TREE);
437 - auto runningProcess = process.Start();
438 -
439 - // N.B. The job cannot be assigned at process creation time as the packaged process
440 - // creation path will assign the new process to a per package job object.
441 - // In the case of multiple processes running in a single package, assigning
442 - // the new process to the per package job object will fail for the second request
443 - // since both jobs already have processes which prevents a job hierarchy from
444 - // being established.
445 - auto job = CreateJob();
446 -
447 - // Assign the process to the job, ignoring failures when the process has
448 - // terminated.
449 - //
450 - // N.B. Assigning the job after process creation without CREATE_SUSPENDED is
451 - // safe to do here since only the new child process will be in the job
452 - // object. None of the grandchildren processes are included since the
453 - // job is created with JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK.
454 - if (!AssignProcessToJobObject(job.get(), runningProcess.get()))
455 - {
456 - auto lastError = GetLastError();
457 - if (lastError != ERROR_ACCESS_DENIED)
458 - {
459 - THROW_WIN32(lastError);
460 - }
461 - }
462 -
463 - return static_cast<int>(SubProcess::GetExitCode(runningProcess.get()));
464 -}
465 -
244 template <typename TInterface>
245 wil::com_ptr<TInterface> wsl::windows::common::wslutil::CoGetCallContext()
246 {
@@ -1208,21 +986,6 @@ std::vector<DWORD> wsl::windows::common::wslutil::ListRunningProcesses()
986 return pids;
987 }
988
1211 -void wsl::windows::common::wslutil::MsiMessageCallback(INSTALLMESSAGE type, LPCWSTR message)
1212 -{
1213 - switch (type)
1214 - {
1215 - case INSTALLMESSAGE_ERROR:
1216 - case INSTALLMESSAGE_FATALEXIT:
1217 - case INSTALLMESSAGE_WARNING:
1218 - wprintf(L"%ls\n", message);
1219 - break;
1220 -
1221 - default:
1222 - break;
1223 - }
1224 -}
1225 -
989 std::pair<wil::unique_hfile, wil::unique_hfile> wsl::windows::common::wslutil::OpenAnonymousPipe(DWORD Size, bool ReadPipeOverlapped, bool WritePipeOverlapped)
990 {
991 // Default to 4096 byte buffer, just like CreatePipe().
@@ -1377,171 +1140,6 @@ wil::unique_hlocal_string wsl::windows::common::wslutil::SidToString(_In_ PSID U
1140 return sid;
1141 }
1142
1380 -int WINAPI InstallRecordHandler(void* context, UINT messageType, LPCWSTR message)
1381 -{
1382 - try
1383 - {
1384 - WSL_LOG("MSIMessage", TraceLoggingValue(messageType, "type"), TraceLoggingValue(message, "message"));
1385 - auto type = (INSTALLMESSAGE)(0xFF000000 & (UINT)messageType);
1386 -
1387 - if (type == INSTALLMESSAGE_ERROR || type == INSTALLMESSAGE_FATALEXIT || type == INSTALLMESSAGE_WARNING)
1388 - {
1389 - WriteInstallLog(std::format("MSI message: {}", message));
1390 - }
1391 -
1392 - auto* callback = reinterpret_cast<const std::function<void(UINT, LPCWSTR)>*>(context);
1393 - if (callback != nullptr)
1394 - {
1395 - (*callback)(type, message);
1396 - }
1397 - }
1398 - CATCH_LOG();
1399 -
1400 - return IDOK;
1401 -}
1402 -
1403 -void ConfigureMsiLogging(_In_opt_ LPCWSTR LogFile, _In_ const std::function<void(INSTALLMESSAGE, LPCWSTR)>& Callback)
1404 -{
1405 - if (LogFile != nullptr)
1406 - {
1407 - LOG_IF_WIN32_ERROR(MsiEnableLog(INSTALLLOGMODE_VERBOSE | INSTALLLOGMODE_EXTRADEBUG | INSTALLLOGMODE_PROGRESS, LogFile, 0));
1408 - }
1409 -
1410 - MsiSetExternalUI(
1411 - &InstallRecordHandler,
1412 - INSTALLLOGMODE_FATALEXIT | INSTALLLOGMODE_ERROR | INSTALLLOGMODE_WARNING | INSTALLLOGMODE_USER | INSTALLLOGMODE_INFO |
1413 - INSTALLLOGMODE_RESOLVESOURCE | INSTALLLOGMODE_OUTOFDISKSPACE | INSTALLLOGMODE_ACTIONSTART | INSTALLLOGMODE_ACTIONDATA |
1414 - INSTALLLOGMODE_COMMONDATA | INSTALLLOGMODE_INITIALIZE | INSTALLLOGMODE_TERMINATE | INSTALLLOGMODE_SHOWDIALOG,
1415 - (void*)&Callback);
1416 -
1417 - MsiSetInternalUI(INSTALLUILEVEL(INSTALLUILEVEL_NONE | INSTALLUILEVEL_UACONLY | INSTALLUILEVEL_SOURCERESONLY), nullptr);
1418 -}
1419 -
1420 -int wsl::windows::common::wslutil::UpdatePackage(bool PreRelease, bool Repair)
1421 -{
1422 - // Register a console control handler so "^C" is not printed when the app platform terminates the process.
1423 - THROW_IF_WIN32_BOOL_FALSE(SetConsoleCtrlHandler(
1424 - [](DWORD ctrlType) {
1425 - if (ctrlType == CTRL_C_EVENT)
1426 - {
1427 - ExitProcess(0);
1428 - }
1429 - return FALSE;
1430 - },
1431 - TRUE));
1432 -
1433 - auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [] { SetConsoleCtrlHandler(nullptr, FALSE); });
1434 -
1435 - try
1436 - {
1437 - return UpdatePackageImpl(PreRelease, Repair);
1438 - }
1439 - catch (...)
1440 - {
1441 - // Rethrowing via WIL is required for the error context to be properly set in case a winrt exception was thrown.
1442 - THROW_HR(wil::ResultFromCaughtException());
1443 - }
1444 -}
1445 -
1446 -UINT wsl::windows::common::wslutil::UpgradeViaMsi(
1447 - _In_ LPCWSTR PackageLocation, _In_opt_ LPCWSTR ExtraArgs, _In_opt_ LPCWSTR LogFile, _In_ const std::function<void(INSTALLMESSAGE, LPCWSTR)>& Callback)
1448 -{
1449 - WriteInstallLog(std::format("Upgrading via MSI package: {}. Args: {}", PackageLocation, ExtraArgs != nullptr ? ExtraArgs : L""));
1450 -
1451 - ConfigureMsiLogging(LogFile, Callback);
1452 -
1453 - auto result = MsiInstallProduct(PackageLocation, ExtraArgs);
1454 - WSL_LOG(
1455 - "MsiInstallResult",
1456 - TraceLoggingValue(result, "result"),
1457 - TraceLoggingValue(ExtraArgs != nullptr ? ExtraArgs : L"", "ExtraArgs"));
1458 -
1459 - WriteInstallLog(std::format("MSI upgrade result: {}", result));
1460 -
1461 - return result;
1462 -}
1463 -
1464 -UINT wsl::windows::common::wslutil::UninstallViaMsi(_In_opt_ LPCWSTR LogFile, _In_ const std::function<void(INSTALLMESSAGE, LPCWSTR)>& Callback)
1465 -{
1466 - const auto key = OpenLxssMachineKey(KEY_READ);
1467 - const auto productCode = ReadString(key.get(), L"Msi", L"ProductCode", nullptr);
1468 -
1469 - WriteInstallLog(std::format("Uninstalling MSI package: {}", productCode));
1470 -
1471 - ConfigureMsiLogging(LogFile, Callback);
1472 -
1473 - auto result = MsiConfigureProduct(productCode.c_str(), 0, INSTALLSTATE_ABSENT);
1474 - WSL_LOG("MsiUninstallResult", TraceLoggingValue(result, "result"));
1475 -
1476 - WriteInstallLog(std::format("MSI package uninstall result: {}", result));
1477 -
1478 - return result;
1479 -}
1480 -
1481 -wil::unique_hfile wsl::windows::common::wslutil::ValidateFileSignature(LPCWSTR Path)
1482 -{
1483 - wil::unique_hfile fileHandle{CreateFileW(Path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr)};
1484 - THROW_LAST_ERROR_IF(!fileHandle);
1485 -
1486 - GUID action = WINTRUST_ACTION_GENERIC_VERIFY_V2;
1487 - WINTRUST_DATA trust{};
1488 - trust.cbStruct = sizeof(trust);
1489 - trust.dwUIChoice = WTD_UI_NONE;
1490 - trust.dwUnionChoice = WTD_CHOICE_FILE;
1491 - trust.dwStateAction = WTD_STATEACTION_VERIFY;
1492 -
1493 - WINTRUST_FILE_INFO file = {0};
1494 - file.cbStruct = sizeof(file);
1495 - file.hFile = fileHandle.get();
1496 - trust.pFile = &file;
1497 -
1498 - auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&]() {
1499 - trust.dwStateAction = WTD_STATEACTION_CLOSE;
1500 - WinVerifyTrust(nullptr, &action, &trust);
1501 - });
1502 -
1503 - THROW_IF_WIN32_ERROR(WinVerifyTrust(nullptr, &action, &trust));
1504 -
1505 - return fileHandle;
1506 -}
1507 -
1508 -void wsl::windows::common::wslutil::WriteInstallLog(const std::string& Content)
1509 -try
1510 -{
1511 - static std::wstring path = wil::GetWindowsDirectoryW<std::wstring>() + L"\\temp\\wsl-install-log.txt";
1512 -
1513 - // Wait up to 10 seconds for the log file mutex
1514 - wil::unique_handle mutex{CreateMutex(nullptr, true, L"Global\\WslInstallLog")};
1515 - THROW_LAST_ERROR_IF(!mutex);
1516 -
1517 - THROW_LAST_ERROR_IF(WaitForSingleObject(mutex.get(), 10 * 1000) != WAIT_OBJECT_0);
1518 -
1519 - wil::unique_handle file{CreateFile(
1520 - path.c_str(), GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_ALWAYS, 0, nullptr)};
1521 -
1522 - THROW_LAST_ERROR_IF(!file);
1523 -
1524 - LARGE_INTEGER size{};
1525 - THROW_IF_WIN32_BOOL_FALSE(GetFileSizeEx(file.get(), &size));
1526 -
1527 - // Append to the file if its size is below 10MB, otherwise truncate.
1528 - if (size.QuadPart < 10 * _1MB)
1529 - {
1530 - THROW_LAST_ERROR_IF(SetFilePointer(file.get(), 0, nullptr, FILE_END) == INVALID_SET_FILE_POINTER);
1531 - }
1532 - else
1533 - {
1534 - THROW_IF_WIN32_BOOL_FALSE(SetEndOfFile(file.get()));
1535 - }
1536 -
1537 - static auto processName = wil::GetModuleFileNameW<std::wstring>();
1538 - auto logLine = std::format("{:%FT%TZ} {}[{}]: {}\n", std::chrono::system_clock::now(), processName, WSL_PACKAGE_VERSION, Content);
1539 -
1540 - DWORD bytesWritten{};
1541 - THROW_IF_WIN32_BOOL_FALSE(WriteFile(file.get(), logLine.c_str(), static_cast<DWORD>(logLine.size()), &bytesWritten, nullptr));
1542 -}
1543 -CATCH_LOG();
1544 -
1143 winrt::Windows::Management::Deployment::PackageVolume wsl::windows::common::wslutil::GetSystemVolume()
1144 try
1145 {
src/windows/common/wslutil.h
-14
@@ -70,8 +70,6 @@ void AssertValidPrintfArg()
70 static_assert(std::is_fundamental_v<T> || std::is_same_v<wchar_t*, T> || std::is_same_v<char*, T> || std::is_same_v<HRESULT, T>);
71 }
72
73 -int CallMsiPackage();
74 -
73 template <typename TInterface>
74 wil::com_ptr<TInterface> CoGetCallContext();
75
@@ -153,8 +151,6 @@ bool IsVirtualMachinePlatformInstalled();
151
152 std::vector<DWORD> ListRunningProcesses();
153
156 -void MsiMessageCallback(INSTALLMESSAGE type, LPCWSTR message);
157 -
154 std::pair<wil::unique_hfile, wil::unique_hfile> OpenAnonymousPipe(DWORD Size, bool ReadPipeOverlapped, bool WritePipeOverlapped);
155
156 wil::unique_handle OpenCallingProcess(_In_ DWORD access);
@@ -198,18 +194,8 @@ void SetCrtEncoding(int Mode);
194
195 void SetThreadDescription(LPCWSTR Name);
196
201 -wil::unique_hfile ValidateFileSignature(LPCWSTR Path);
202 -
197 wil::unique_hlocal_string SidToString(_In_ PSID Sid);
198
205 -int UpdatePackage(bool PreRelease, bool Repair);
206 -
207 -UINT UpgradeViaMsi(_In_ LPCWSTR PackageLocation, _In_opt_ LPCWSTR ExtraArgs, _In_opt_ LPCWSTR LogFile, _In_ const std::function<void(INSTALLMESSAGE, LPCWSTR)>& callback);
208 -
209 -UINT UninstallViaMsi(_In_opt_ LPCWSTR LogFile, _In_ const std::function<void(INSTALLMESSAGE, LPCWSTR)>& callback);
210 -
211 -void WriteInstallLog(const std::string& Content);
212 -
199 winrt::Windows::Management::Deployment::PackageVolume GetSystemVolume();
200
201 } // namespace wsl::windows::common::wslutil
src/windows/service/exe/CMakeLists.txt
+3 -1
@@ -57,7 +57,9 @@ add_compile_definitions(USE_COM_CONTEXT_DEF=1)
57 set_target_properties(wslservice PROPERTIES LINK_FLAGS "/merge:minATL=.rdata /include:__minATLObjMap_LxssUserSession_COM")
58 target_link_libraries(wslservice
59 ${COMMON_LINK_LIBRARIES}
60 - computecore
60 + ${MSI_LINK_LIBRARIES}
61 + ${HCS_LINK_LIBRARIES}
62 + ${SERVICE_LINK_LIBRARIES}
63 common
64 configfile
65 legacy_stdio_definitions
src/windows/service/exe/PluginManager.cpp
+2 -1
@@ -13,6 +13,7 @@ Abstract:
13 --*/
14
15 #include "precomp.h"
16 +#include "install.h"
17 #include "PluginManager.h"
18 #include "WslPluginApi.h"
19 #include "LxssUserSessionFactory.h"
@@ -150,7 +151,7 @@ void PluginManager::LoadPlugin(LPCWSTR Name, LPCWSTR ModulePath)
151 wil::unique_hfile pluginHandle;
152 if constexpr (wsl::shared::OfficialBuild)
153 {
153 - pluginHandle = wsl::windows::common::wslutil::ValidateFileSignature(ModulePath);
154 + pluginHandle = wsl::windows::common::install::ValidateFileSignature(ModulePath);
155 WI_ASSERT(pluginHandle.is_valid());
156 }
157
src/windows/wsl/CMakeLists.txt
+4 -1
@@ -9,8 +9,11 @@ add_executable(wsl ${SOURCES} ${HEADERS})
9
10 target_link_libraries(wsl
11 ${COMMON_LINK_LIBRARIES}
12 + ${MSI_LINK_LIBRARIES}
13 common
13 - runtimeobject.lib)
14 + runtimeobject.lib
15 + delayimp.lib)
16
17 +set_target_properties(wsl PROPERTIES LINK_FLAGS "/DELAYLOAD:msi.dll /DELAYLOAD:WINTRUST.dll")
18 target_precompile_headers(wsl REUSE_FROM common)
19 set_target_properties(wsl PROPERTIES FOLDER windows)
\ No newline at end of file
src/windows/wslg/CMakeLists.txt
+4 -1
@@ -12,7 +12,10 @@ add_dependencies(wslg
12
13 target_link_libraries(wslg
14 ${COMMON_LINK_LIBRARIES}
15 - common)
15 + ${MSI_LINK_LIBRARIES}
16 + common
17 + delayimp.lib)
18
19 +set_target_properties(wslg PROPERTIES LINK_FLAGS "/DELAYLOAD:msi.dll /DELAYLOAD:WINTRUST.dll")
20 target_precompile_headers(wslg REUSE_FROM common)
21 set_target_properties(wslg PROPERTIES FOLDER windows)
\ No newline at end of file
src/windows/wslinstall/CMakeLists.txt
+1 -1
@@ -10,8 +10,8 @@ target_precompile_headers(wslinstall REUSE_FROM common)
10
11 target_link_libraries(wslinstall
12 ${COMMON_LINK_LIBRARIES}
13 + ${MSI_LINK_LIBRARIES}
14 common
15 legacy_stdio_definitions
15 - Msi.lib
16 Crypt32.lib
17 sfc.lib)
\ No newline at end of file
src/windows/wslinstall/DllMain.cpp
+2
@@ -13,6 +13,7 @@ Abstract:
13 --*/
14
15 #include "precomp.h"
16 +#include "install.h"
17 #include <msiquery.h>
18 #include <winrt/Windows.ApplicationModel.Core.h>
19 #include <winrt/Windows.Foundation.Collections.h>
@@ -24,6 +25,7 @@ using unique_msi_handle = wil::unique_any<MSIHANDLE, decltype(MsiCloseHandle), &
25
26 using namespace wsl::windows::common::registry;
27 using namespace wsl::windows::common::wslutil;
28 +using namespace wsl::windows::common::install;
29
30 static constexpr auto c_progIdPrefix{L"App."};
31 static constexpr auto c_protocolProgIdSuffix{L".Protocol"};
src/windows/wslinstaller/exe/CMakeLists.txt
+1
@@ -16,6 +16,7 @@ add_dependencies(wslinstaller wslinstalleridl)
16 set_target_properties(wslinstaller PROPERTIES LINK_FLAGS "/merge:minATL=.rdata /include:__minATLObjMap_WslInstaller_COM")
17 target_link_libraries(wslinstaller
18 ${COMMON_LINK_LIBRARIES}
19 + ${MSI_LINK_LIBRARIES}
20 common
21 legacy_stdio_definitions)
22
src/windows/wslinstaller/exe/WslInstaller.cpp
+3 -2
@@ -13,6 +13,7 @@ Abstract:
13 --*/
14
15 #include "precomp.h"
16 +#include "install.h"
17 #include "WslInstaller.h"
18
19 extern wil::unique_event g_stopEvent;
@@ -75,7 +76,7 @@ std::pair<UINT, std::wstring> InstallMsipackageImpl()
76 }
77 };
78
78 - auto result = wsl::windows::common::wslutil::UpgradeViaMsi(
79 + auto result = wsl::windows::common::install::UpgradeViaMsi(
80 GetMsiPackagePath().c_str(), L"SKIPMSIX=1", logFile.has_value() ? logFile->c_str() : nullptr, messageCallback);
81
82 WSL_LOG("MSIUpgradeResult", TraceLoggingValue(result, "result"), TraceLoggingValue(errors.c_str(), "errorMessage"));
@@ -140,7 +141,7 @@ std::shared_ptr<InstallContext> LaunchInstall()
141 return {};
142 }
143
143 - wsl::windows::common::wslutil::WriteInstallLog(std::format("Starting upgrade via WslInstaller. Previous version: {}", existingVersion));
144 + wsl::windows::common::install::WriteInstallLog(std::format("Starting upgrade via WslInstaller. Previous version: {}", existingVersion));
145
146 // Return an existing install if any
147 if (auto ptr = weak_context.lock(); ptr != nullptr)
test/windows/CMakeLists.txt
+3
@@ -24,6 +24,9 @@ target_link_libraries(wsltests
24 common
25 ${TAEF_LINK_LIBRARIES}
26 ${COMMON_LINK_LIBRARIES}
27 + ${MSI_LINK_LIBRARIES}
28 + ${HCS_LINK_LIBRARIES}
29 + ${SERVICE_LINK_LIBRARIES}
30 VirtDisk.lib
31 Wer.lib
32 Dbghelp.lib
test/windows/UnitTests.cpp
+2 -1
@@ -15,6 +15,7 @@ Abstract:
15 #include "precomp.h"
16
17 #include "Common.h"
18 +#include "install.h"
19 #include <AclAPI.h>
20 #include <fstream>
21 #include <filesystem>
@@ -2350,7 +2351,7 @@ Error code: Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND
2351 {
2352 LogInfo("Validating signature for: %ls", e.path().c_str());
2353
2353 - wsl::windows::common::wslutil::ValidateFileSignature(e.path().c_str());
2354 + wsl::windows::common::install::ValidateFileSignature(e.path().c_str());
2355 signedFiles++;
2356 }
2357 }