| 1 | /*++ |
| 2 | |
| 3 | Copyright (c) Microsoft. All rights reserved. |
| 4 | |
| 5 | Module Name: |
| 6 | |
| 7 | ServiceMain.cpp |
| 8 | |
| 9 | Abstract: |
| 10 | |
| 11 | This file contains the entrypoint for WslInstallerService. |
| 12 | |
| 13 | --*/ |
| 14 | |
| 15 | #include "precomp.h" |
| 16 | #include "comservicehelper.h" |
| 17 | #include "WslTelemetry.h" |
| 18 | #include "WslInstallerFactory.h" |
| 19 | |
| 20 | wil::unique_event g_stopEvent{wil::EventOptions::ManualReset}; |
| 21 | |
| 22 | static constexpr auto c_serviceName = L"WslInstaller"; |
| 23 | |
| 24 | CoCreatableClassWrlCreatorMapInclude(WslInstaller); |
| 25 | |
| 26 | struct WslInstallSecurityPolicy |
| 27 | { |
| 28 | static LPCWSTR GetSDDLText() |
| 29 | { |
| 30 | // COM Access and Launch permissions allowed for authenticated user, principal self, and system. |
| 31 | // 0xB = (COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL | COM_RIGHTS_ACTIVATE_LOCAL) |
| 32 | // N.B. This should be kept in sync with the security descriptor in the appxmanifest. |
| 33 | return L"O:BAG:BAD:(A;;0xB;;;AU)(A;;0xB;;;PS)(A;;0xB;;;SY)"; |
| 34 | } |
| 35 | }; |
| 36 | |
| 37 | class WslInstallerService |
| 38 | : public Windows::Internal::Service<WslInstallerService, Windows::Internal::ShutdownAfterLastObjectReleased, WslInstallSecurityPolicy> |
| 39 | { |
| 40 | public: |
| 41 | static wchar_t* GetName() |
| 42 | { |
| 43 | return const_cast<LPWSTR>(c_serviceName); |
| 44 | } |
| 45 | |
| 46 | static HRESULT OnServiceStarting(); |
| 47 | HRESULT ServiceStarted(); |
| 48 | static void ServiceStopped(); |
| 49 | static bool AutoInstallEnabled(); |
| 50 | }; |
| 51 | |
| 52 | bool WslInstallerService::AutoInstallEnabled() |
| 53 | try |
| 54 | { |
| 55 | const auto key = wsl::windows::common::registry::OpenLxssMachineKey(KEY_READ); |
| 56 | |
| 57 | auto value = wsl::windows::common::registry::ReadDword(key.get(), L"MSI", L"AutoUpgradeViaMsix", 1); |
| 58 | WSL_LOG("AutoUpgradeViaMsix", TraceLoggingLevel(WINEVENT_LEVEL_INFO), TraceLoggingValue(value, "setting")); |
| 59 | |
| 60 | return value == 1; |
| 61 | } |
| 62 | catch (...) |
| 63 | { |
| 64 | LOG_CAUGHT_EXCEPTION(); |
| 65 | return false; |
| 66 | } |
| 67 | |
| 68 | HRESULT WslInstallerService::OnServiceStarting() |
| 69 | { |
| 70 | wil::g_fResultFailFastUnknownExceptions = false; |
| 71 | wsl::windows::common::wslutil::ConfigureCrt(); |
| 72 | |
| 73 | WslTraceLoggingInitialize(WslServiceTelemetryProvider, !wsl::shared::OfficialBuild); |
| 74 | wsl::windows::common::security::ApplyProcessMitigationPolicies(); |
| 75 | |
| 76 | return S_OK; |
| 77 | } |
| 78 | |
| 79 | void Stop() |
| 80 | { |
| 81 | const wil::unique_schandle scm{OpenSCManagerW(nullptr, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS)}; |
| 82 | THROW_LAST_ERROR_IF(!scm); |
| 83 | |
| 84 | const wil::unique_schandle self{OpenServiceW(scm.get(), c_serviceName, SERVICE_STOP | SERVICE_QUERY_STATUS)}; |
| 85 | THROW_LAST_ERROR_IF(!self); |
| 86 | |
| 87 | SERVICE_STATUS status{}; |
| 88 | THROW_IF_WIN32_BOOL_FALSE(ControlService(self.get(), SERVICE_CONTROL_STOP, &status)); |
| 89 | } |
| 90 | |
| 91 | HRESULT WslInstallerService::ServiceStarted() |
| 92 | { |
| 93 | WSL_LOG("WslInstallServiceStarted", TraceLoggingLevel(WINEVENT_LEVEL_INFO)); |
| 94 | |
| 95 | if (AutoInstallEnabled()) |
| 96 | { |
| 97 | const auto install = LaunchInstall(); |
| 98 | if (!install) |
| 99 | { |
| 100 | ReportCurrentStatus(); |
| 101 | StopAsync(); |
| 102 | return S_OK; |
| 103 | } |
| 104 | |
| 105 | THROW_LAST_ERROR_IF(WaitForSingleObject(install->Thread.get(), INFINITE) != WAIT_OBJECT_0); |
| 106 | } |
| 107 | |
| 108 | return S_OK; |
| 109 | } |
| 110 | |
| 111 | void WslInstallerService::ServiceStopped() |
| 112 | { |
| 113 | WSL_LOG("WslInstallServiceStopping", TraceLoggingLevel(WINEVENT_LEVEL_INFO)); |
| 114 | |
| 115 | g_stopEvent.SetEvent(); |
| 116 | ClearSessions(); |
| 117 | } |
| 118 | |
| 119 | int __cdecl wmain() |
| 120 | { |
| 121 | WslInstallerService::ProcessMain(); |
| 122 | return 0; |
| 123 | } |