| // Copyright 2018 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROME_INSTALLER_UTIL_INSTALL_SERVICE_WORK_ITEM_IMPL_H_ |
| #define CHROME_INSTALLER_UTIL_INSTALL_SERVICE_WORK_ITEM_IMPL_H_ |
| |
| #include <windows.h> |
| |
| #include <string> |
| #include <vector> |
| |
| #include "base/command_line.h" |
| #include "base/gtest_prod_util.h" |
| #include "base/strings/cstring_view.h" |
| #include "base/win/scoped_handle.h" |
| #include "base/win/windows_types.h" |
| #include "chrome/installer/util/work_item_list.h" |
| |
| namespace base { |
| |
| class CommandLine; |
| |
| } // namespace base |
| |
| namespace installer { |
| |
| // Helper class for the implementation of InstallServiceWorkItem. |
| class InstallServiceWorkItemImpl { |
| public: |
| struct ServiceConfig { |
| ServiceConfig(); |
| ServiceConfig(uint32_t service_type, |
| uint32_t service_start_type, |
| uint32_t service_error_control, |
| const std::wstring& service_cmd_line, |
| const wchar_t* dependencies_multi_sz, |
| const std::wstring& service_display_name); |
| |
| ServiceConfig(const ServiceConfig& rhs); |
| ServiceConfig& operator=(const ServiceConfig& rhs) = default; |
| |
| ServiceConfig(ServiceConfig&& rhs); |
| ServiceConfig& operator=(ServiceConfig&& rhs) = default; |
| |
| ~ServiceConfig(); |
| |
| friend bool operator==(const ServiceConfig& lhs, const ServiceConfig& rhs); |
| |
| bool is_valid = false; |
| uint32_t type = SERVICE_NO_CHANGE; |
| uint32_t start_type = SERVICE_NO_CHANGE; |
| uint32_t error_control = SERVICE_NO_CHANGE; |
| std::wstring cmd_line; |
| std::vector<wchar_t> dependencies; |
| std::wstring display_name; |
| }; |
| |
| InstallServiceWorkItemImpl(const std::wstring& service_name, |
| const std::wstring& display_name, |
| const std::wstring& description, |
| uint32_t start_type, |
| const base::CommandLine& service_cmd_line, |
| const base::CommandLine& com_service_cmd_line_args, |
| const std::wstring& registry_path, |
| const std::vector<GUID>& clsids, |
| const std::vector<GUID>& iids); |
| |
| InstallServiceWorkItemImpl(const InstallServiceWorkItemImpl&) = delete; |
| InstallServiceWorkItemImpl& operator=(const InstallServiceWorkItemImpl&) = |
| delete; |
| |
| ~InstallServiceWorkItemImpl(); |
| |
| bool DoImpl(); |
| void RollbackImpl(); |
| bool DeleteServiceImpl(); |
| |
| // Member functions that help with service installation or upgrades. |
| |
| // `MakeUpgradeServiceConfig()` returns a differential `ServiceConfig` that |
| // facilitates passing it with minimal changes subsequently to |
| // `ChangeServiceConfig()`. This way, `ChangeServiceConfig()` only asks the |
| // Windows SCM to make changes where they differ from the existing service |
| // configuration. |
| ServiceConfig MakeUpgradeServiceConfig(const ServiceConfig& original_config); |
| |
| // Takes the `new_config` returned by `MakeUpgradeServiceConfig()` and |
| // returns true if `new_config` does not match the default configuration. |
| bool IsUpgradeNeeded(const ServiceConfig& new_config); |
| |
| bool ChangeServiceConfig(const ServiceConfig& config); |
| bool DeleteCurrentService(); |
| |
| // Helper functions for service install/upgrade/delete/rollback. |
| bool OpenService(); |
| bool GetServiceConfig(ServiceConfig* config) const; |
| |
| // Stores in the registry a versioned service name generated by |
| // GenerateVersionedServiceName(). |
| bool CreateAndSetServiceName() const; |
| |
| // Returns the versioned service name if one exists in the registry under the |
| // named value service_name_. In other cases, it returns service_name_. |
| std::wstring GetCurrentServiceName() const; |
| |
| // Returns a display name of the following format: |
| // "Chrome Elevation Service (ChromeElevationService)" |
| // or: |
| // "Chrome Elevation Service (ChromeElevationService1d59511c58deaa8)" |
| // |
| // The "Chrome Elevation Service" fragment is the display_name_, and the |
| // "ChromeElevationService1d59511c58deaa8" fragment is the versioned service |
| // name returned from GetCurrentServiceName(). |
| std::wstring GetCurrentServiceDisplayName() const; |
| |
| // Copies and returns a vector containing a sequence of C-style strings |
| // terminated with '\0\0'. Return an empty vector if the input is nullptr. |
| static std::vector<wchar_t> MultiSzToVector(const wchar_t* multi_sz); |
| |
| // Returns true if a cursory check appears to indicate that the service |
| // hosting `clsid` is installed. |
| static bool IsComServiceInstalled(const GUID& clsid); |
| |
| // Returns the current name of the service as registered with the SCM. |
| static std::wstring GetCurrentServiceName(base::wcstring_view service_name, |
| base::wcstring_view registry_path); |
| |
| private: |
| class ScHandleTraits { |
| public: |
| using Handle = SC_HANDLE; |
| |
| ScHandleTraits() = delete; |
| ScHandleTraits(const ScHandleTraits&) = delete; |
| ScHandleTraits& operator=(const ScHandleTraits&) = delete; |
| |
| static bool CloseHandle(SC_HANDLE handle) { |
| return ::CloseServiceHandle(handle) != FALSE; |
| } |
| |
| static bool IsHandleValid(SC_HANDLE handle) { return handle != nullptr; } |
| |
| static SC_HANDLE NullHandle() { return nullptr; } |
| }; |
| |
| using ScopedScHandle = |
| base::win::GenericScopedHandle<ScHandleTraits, |
| base::win::DummyVerifierTraits>; |
| |
| // This is the core functionality for installing the Windows Service itself. |
| bool DoInstallService(); |
| |
| // This is the core functionality for COM registration for the Service. |
| bool DoComRegistration(); |
| |
| // Returns the service description by querying the service. |
| std::wstring GetCurrentServiceDescription() const; |
| |
| // Sets the service description displayed in the services control panel. |
| void SetDescription(); |
| |
| // Member functions that help with service installation or upgrades. |
| bool InstallNewService(); |
| |
| // Upgrades an existing service's configuration in-place. Returns true if the |
| // service was already properly configured, or if it was successfully |
| // upgraded; otherwise, returns false in case of any failure. |
| // Side-effects of this function: |
| // * Saves the original service's config in |original_service_config_| if |
| // the new service configuration will be different. |
| // |original_service_config_| is used in rollback scenarios, specifically |
| // in ReinstallOriginalService() and RestoreOriginalServiceConfig(). |
| // * Sets |rollback_existing_service_| to true if the service is |
| // successfully upgraded, which is used by RollbackImpl(). |
| bool UpgradeService(); |
| |
| // Member functions that help with rollbacks. |
| bool ReinstallOriginalService(); |
| bool RestoreOriginalServiceConfig(); |
| |
| // Helper functions for service install/upgrade/delete/rollback. |
| bool InstallService(const ServiceConfig& config); |
| bool DeleteService(ScopedScHandle service) const; |
| |
| // Generates a versioned service name prefixed with service_name_ and suffixed |
| // with the current system time in hexadecimal format. |
| std::wstring GenerateVersionedServiceName() const; |
| |
| // Persists the given service name in the registry. |
| bool SetServiceName(const std::wstring& service_name) const; |
| |
| // The COM registration is done using a contained WorkItemList. |
| std::unique_ptr<WorkItemList> com_registration_work_items_; |
| |
| // The service name, or in the case of a conflict, the prefix for the service |
| // name. |
| const std::wstring service_name_; |
| |
| // The service name displayed to the user. |
| const std::wstring display_name_; |
| |
| // The service description displayed in the services control panel. |
| const std::wstring description_; |
| |
| // The service start options. This parameter is typically SERVICE_AUTO_START |
| // or SERVICE_DEMAND_START. |
| const uint32_t start_type_; |
| |
| // The desired service command line. |
| const base::CommandLine service_cmd_line_; |
| |
| // The SCM will pass any switches specified in `com_service_cmd_line_args_` to |
| // ServiceMain() during COM activation. |
| const base::CommandLine com_service_cmd_line_args_; |
| |
| // The path under HKEY_LOCAL_MACHINE where the service persists information, |
| // such as a versioned service name. For legacy reasons, this path is mapped |
| // to the 32-bit view of the registry. |
| const std::wstring registry_path_; |
| |
| // If COM CLSID/AppId registration is required, |clsids_| would be populated. |
| const std::vector<GUID> clsids_; |
| |
| // If COM Interface/Typelib registration is required, |iids_| would be |
| // populated. |
| const std::vector<GUID> iids_; |
| |
| ScopedScHandle scm_; |
| ScopedScHandle service_; |
| |
| // Rollback-specific data. |
| |
| // True if original_service_config_ and service_ are both valid, and the |
| // former should be applied to the latter on rollback. |
| bool rollback_existing_service_; |
| |
| // True if service_ represents a newly-installed service that is to be deleted |
| // on rollback. |
| bool rollback_new_service_; |
| |
| // The configuration of a pre-existing service on the machine that may have |
| // been modified or deleted. |
| ServiceConfig original_service_config_; |
| |
| // The service name prior to any modifications; may be either |service_name_| |
| // or a value read from the registry. |
| std::wstring original_service_name_; |
| |
| // True if a pre-existing service (named |original_service_name_|) could not |
| // be deleted and still exists on rollback. |
| bool original_service_still_exists_; |
| |
| FRIEND_TEST_ALL_PREFIXES(InstallServiceWorkItemTest, |
| Do_UpgradeChangedCmdLineStartTypeCOMArgs); |
| }; |
| |
| } // namespace installer |
| |
| #endif // CHROME_INSTALLER_UTIL_INSTALL_SERVICE_WORK_ITEM_IMPL_H_ |