diff options
author | vitalybuka@chromium.org <vitalybuka@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-12 04:20:38 +0000 |
---|---|---|
committer | vitalybuka@chromium.org <vitalybuka@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-12 04:20:38 +0000 |
commit | a9734a2c32754e3f00a0ab9e1e8511288d74f717 (patch) | |
tree | ddc8c79cfc944ac20e1ca9bb5493265e2b4c2c4f /cloud_print | |
parent | ee479cdca22f7c0166ce371af4e432cd21293e90 (diff) | |
download | chromium_src-a9734a2c32754e3f00a0ab9e1e8511288d74f717.zip chromium_src-a9734a2c32754e3f00a0ab9e1e8511288d74f717.tar.gz chromium_src-a9734a2c32754e3f00a0ab9e1e8511288d74f717.tar.bz2 |
Exctracted ServiceController.
BUG=0
Review URL: https://chromiumcodereview.appspot.com/12729003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@187489 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cloud_print')
-rw-r--r-- | cloud_print/service/service.gyp | 2 | ||||
-rw-r--r-- | cloud_print/service/win/cloud_print_service.cc | 195 | ||||
-rw-r--r-- | cloud_print/service/win/service_controller.cc | 182 | ||||
-rw-r--r-- | cloud_print/service/win/service_controller.h | 41 |
4 files changed, 251 insertions, 169 deletions
diff --git a/cloud_print/service/service.gyp b/cloud_print/service/service.gyp index 012c80e..bbf6065 100644 --- a/cloud_print/service/service.gyp +++ b/cloud_print/service/service.gyp @@ -54,6 +54,8 @@ 'win/chrome_launcher.h', 'win/local_security_policy.cc', 'win/local_security_policy.h', + 'win/service_controller.cc', + 'win/service_controller.h', ], }, { diff --git a/cloud_print/service/win/cloud_print_service.cc b/cloud_print/service/win/cloud_print_service.cc index 8d8279b..2577d76 100644 --- a/cloud_print/service/win/cloud_print_service.cc +++ b/cloud_print/service/win/cloud_print_service.cc @@ -16,18 +16,16 @@ #include "base/at_exit.h" #include "base/command_line.h" #include "base/file_util.h" -#include "base/files/file_path.h" #include "base/guid.h" +#include "base/logging.h" #include "base/path_service.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" -#include "base/win/scoped_handle.h" #include "chrome/installer/launcher_support/chrome_launcher_support.h" #include "cloud_print/service/service_state.h" #include "cloud_print/service/service_switches.h" #include "cloud_print/service/win/chrome_launcher.h" -#include "cloud_print/service/win/local_security_policy.h" -#include "cloud_print/service/win/resource.h" +#include "cloud_print/service/win/service_controller.h" #include "printing/backend/print_backend.h" namespace { @@ -37,39 +35,6 @@ const char kChromeIsAvalible[] = "\nChrome is available\n"; const wchar_t kRequirementsFileName[] = L"cloud_print_service_requirements.txt"; const wchar_t kServiceStateFileName[] = L"Service State"; -// The traits class for Windows Service. -class ServiceHandleTraits { - public: - typedef SC_HANDLE Handle; - - // Closes the handle. - static bool CloseHandle(Handle handle) { - return ::CloseServiceHandle(handle) != FALSE; - } - - static bool IsHandleValid(Handle handle) { - return handle != NULL; - } - - static Handle NullHandle() { - return NULL; - } - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(ServiceHandleTraits); -}; - -typedef base::win::GenericScopedHandle< - ServiceHandleTraits, base::win::DummyVerifierTraits> ServiceHandle; - -HRESULT HResultFromLastError() { - HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); - // Something already failed if function called. - if (SUCCEEDED(hr)) - hr = E_FAIL; - return hr; -} - void InvalidUsage() { base::FilePath service_path; CHECK(PathService::Get(base::FILE_EXE, &service_path)); @@ -171,78 +136,21 @@ class CloudPrintServiceModule typedef ATL::CAtlServiceModuleT<CloudPrintServiceModule, IDS_SERVICENAME> Base; - DECLARE_REGISTRY_APPID_RESOURCEID(IDR_CLOUDPRINTSERVICE, - "{8013FB7C-2E3E-4992-B8BD-05C0C4AB0627}") - - CloudPrintServiceModule() : check_requirements_(false) { + CloudPrintServiceModule() + : check_requirements_(false), + controller_(new ServiceController(m_szServiceName)) { } + static wchar_t* GetAppIdT() { + return ServiceController::GetAppIdT(); + }; + HRESULT InitializeSecurity() { // TODO(gene): Check if we need to call CoInitializeSecurity and provide // the appropriate security settings for service. return S_OK; } - HRESULT InstallService(const string16& user, - const string16& password, - const char* run_switch) { - // TODO(vitalybuka): consider "lite" version if we don't want unregister - // printers here. - HRESULT hr = UninstallService(); - if (FAILED(hr)) - return hr; - - hr = UpdateRegistryAppId(true); - if (FAILED(hr)) - return hr; - - base::FilePath service_path; - CHECK(PathService::Get(base::FILE_EXE, &service_path)); - CommandLine command_line(service_path); - command_line.AppendSwitch(run_switch); - command_line.AppendSwitchPath(kUserDataDirSwitch, user_data_dir_); - - LocalSecurityPolicy local_security_policy; - if (local_security_policy.Open()) { - if (!local_security_policy.IsPrivilegeSet(user, kSeServiceLogonRight)) { - LOG(WARNING) << "Setting " << kSeServiceLogonRight << " for " << user; - if (!local_security_policy.SetPrivilege(user, kSeServiceLogonRight)) { - LOG(ERROR) << "Failed to set" << kSeServiceLogonRight; - LOG(ERROR) << "Make sure you can run the service as " << user << "."; - } - } - } else { - LOG(ERROR) << "Failed to open security policy."; - } - - ServiceHandle scm; - hr = OpenServiceManager(&scm); - if (FAILED(hr)) - return hr; - - ServiceHandle service( - ::CreateService( - scm, m_szServiceName, m_szServiceName, SERVICE_ALL_ACCESS, - SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, - command_line.GetCommandLineString().c_str(), NULL, NULL, NULL, - user.empty() ? NULL : user.c_str(), - password.empty() ? NULL : password.c_str())); - - if (!service.IsValid()) { - LOG(ERROR) << "Failed to install service as " << user << "."; - return HResultFromLastError(); - } - - return S_OK; - } - - HRESULT UninstallService() { - StopService(); - if (!Uninstall()) - return E_FAIL; - return UpdateRegistryAppId(false); - } - bool ParseCommandLine(LPCTSTR lpCmdLine, HRESULT* pnRetCode) { CHECK(pnRetCode); CommandLine command_line(CommandLine::NO_PROGRAM); @@ -292,10 +200,10 @@ class CloudPrintServiceModule user_data_dir_ = command_line.GetSwitchValuePath(kUserDataDirSwitch); if (command_line.HasSwitch(kStopSwitch)) - return StopService(); + return controller_->StopService(); if (command_line.HasSwitch(kUninstallSwitch)) - return UninstallService(); + return controller_->UninstallService(); if (command_line.HasSwitch(kInstallSwitch)) { if (!command_line.HasSwitch(kUserDataDirSwitch)) { @@ -311,16 +219,16 @@ class CloudPrintServiceModule if (FAILED(hr)) return hr; - hr = InstallService(run_as_user.c_str(), run_as_password.c_str(), - kServiceSwitch); + hr = controller_->InstallService(run_as_user, run_as_password, + kServiceSwitch, user_data_dir_); if (SUCCEEDED(hr) && command_line.HasSwitch(kStartSwitch)) - return StartService(); + return controller_->StartService(); return hr; } if (command_line.HasSwitch(kStartSwitch)) - return StartService(); + return controller_->StartService(); if (command_line.HasSwitch(kServiceSwitch) || command_line.HasSwitch(kRequirementsSwitch)) { @@ -340,13 +248,12 @@ class CloudPrintServiceModule return S_FALSE; } - void SelectWindowsAccount(string16* run_as_user, - string16* run_as_password) { + void SelectWindowsAccount(string16* run_as_user, string16* run_as_password) { *run_as_user = GetCurrentUserName(); for (;;) { std::cout << "\nPlease provide Windows account to run service.\n"; *run_as_user = ASCIIToWide(GetOption("Account as DOMAIN\\USERNAME", - WideToASCII(*run_as_user), false)); + WideToASCII(*run_as_user), false)); *run_as_password = ASCIIToWide(GetOption("Password", "", true)); base::FilePath requirements_filename(user_data_dir_); @@ -359,13 +266,13 @@ class CloudPrintServiceModule requirements_filename.value() << "."; continue; } - if (FAILED(InstallService(run_as_user->c_str(), - run_as_password->c_str(), - kRequirementsSwitch))) { + if (FAILED(controller_->InstallService(*run_as_user, *run_as_password, + kRequirementsSwitch, + user_data_dir_))) { continue; } - bool service_started = SUCCEEDED(StartService()); - UninstallService(); + bool service_started = SUCCEEDED(controller_->StartService()); + controller_->UninstallService(); if (!service_started) { LOG(ERROR) << "Failed to start service as " << *run_as_user << "."; continue; @@ -431,7 +338,8 @@ class CloudPrintServiceModule new_contents.size()); if (written != new_contents.size()) { LOG(ERROR) << "Failed to write file " << file.value() << "."; - return HResultFromLastError(); + DWORD last_error = GetLastError(); + return last_error ? HRESULT_FROM_WIN32(last_error) : E_FAIL; } } } @@ -441,59 +349,6 @@ class CloudPrintServiceModule return S_OK; } - HRESULT OpenServiceManager(ServiceHandle* service_manager) { - if (!service_manager) - return E_POINTER; - - service_manager->Set(::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)); - if (!service_manager->IsValid()) - return HResultFromLastError(); - - return S_OK; - } - - HRESULT OpenService(DWORD access, ServiceHandle* service) { - if (!service) - return E_POINTER; - - ServiceHandle scm; - HRESULT hr = OpenServiceManager(&scm); - if (FAILED(hr)) - return hr; - - service->Set(::OpenService(scm, m_szServiceName, access)); - - if (!service->IsValid()) - return HResultFromLastError(); - - return S_OK; - } - - HRESULT StartService() { - ServiceHandle service; - HRESULT hr = OpenService(SERVICE_START, &service); - if (FAILED(hr)) - return hr; - if (!::StartService(service, 0, NULL)) - return HResultFromLastError(); - return S_OK; - } - - HRESULT StopService() { - ServiceHandle service; - HRESULT hr = OpenService(SERVICE_STOP | SERVICE_QUERY_STATUS, &service); - if (FAILED(hr)) - return hr; - SERVICE_STATUS status = {0}; - if (!::ControlService(service, SERVICE_CONTROL_STOP, &status)) - return HResultFromLastError(); - while (::QueryServiceStatus(service, &status) && - status.dwCurrentState > SERVICE_STOPPED) { - Sleep(500); - } - return S_OK; - } - HRESULT CheckRequirements() { base::FilePath requirements_filename(user_data_dir_); requirements_filename = requirements_filename.Append(kRequirementsFileName); @@ -532,6 +387,7 @@ class CloudPrintServiceModule bool check_requirements_; base::FilePath user_data_dir_; scoped_ptr<ChromeLauncher> chrome_; + scoped_ptr<ServiceController> controller_; }; CloudPrintServiceModule _AtlModule; @@ -545,3 +401,4 @@ int main() { base::AtExitManager at_exit; return _AtlModule.WinMain(0); } + diff --git a/cloud_print/service/win/service_controller.cc b/cloud_print/service/win/service_controller.cc new file mode 100644 index 0000000..b9a749d --- /dev/null +++ b/cloud_print/service/win/service_controller.cc @@ -0,0 +1,182 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cloud_print/service/win/service_controller.h" + +#include <atlbase.h> +#include <atlcom.h> +#include <atlctl.h> + +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/path_service.h" +#include "base/win/scoped_handle.h" +#include "cloud_print/service/service_switches.h" +#include "cloud_print/service/win/local_security_policy.h" + +namespace { + +HRESULT HResultFromLastError() { + return GetLastError() ? HRESULT_FROM_WIN32(GetLastError()) : E_FAIL; +} + +// The traits class for Windows Service. +class ServiceHandleTraits { + public: + typedef SC_HANDLE Handle; + + // Closes the handle. + static bool CloseHandle(Handle handle) { + return ::CloseServiceHandle(handle) != FALSE; + } + + static bool IsHandleValid(Handle handle) { + return handle != NULL; + } + + static Handle NullHandle() { + return NULL; + } + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(ServiceHandleTraits); +}; + +typedef base::win::GenericScopedHandle< + ServiceHandleTraits, base::win::DummyVerifierTraits> ServiceHandle; + +HRESULT OpenServiceManager(ServiceHandle* service_manager) { + if (!service_manager) + return E_POINTER; + + service_manager->Set(::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)); + if (!service_manager->IsValid()) + return HResultFromLastError(); + + return S_OK; +} + +HRESULT OpenService(const string16& name, DWORD access, + ServiceHandle* service) { + if (!service) + return E_POINTER; + + ServiceHandle scm; + HRESULT hr = OpenServiceManager(&scm); + if (FAILED(hr)) + return hr; + + service->Set(::OpenService(scm, name.c_str(), access)); + + if (!service->IsValid()) + return HResultFromLastError(); + + return S_OK; +} + +} // namespace + +ServiceController::ServiceController(const string16& name) + : name_(name) { +} + +ServiceController::~ServiceController() { +} + +HRESULT ServiceController::StartService() { + ServiceHandle service; + HRESULT hr = OpenService(name_, SERVICE_START, &service); + if (FAILED(hr)) + return hr; + if (!::StartService(service, 0, NULL)) + return HResultFromLastError(); + return S_OK; +} + +HRESULT ServiceController::StopService() { + ServiceHandle service; + HRESULT hr = OpenService(name_, SERVICE_STOP | SERVICE_QUERY_STATUS, + &service); + if (FAILED(hr)) + return hr; + SERVICE_STATUS status = {0}; + if (!::ControlService(service, SERVICE_CONTROL_STOP, &status)) + return HResultFromLastError(); + while (::QueryServiceStatus(service, &status) && + status.dwCurrentState > SERVICE_STOPPED) { + Sleep(500); + } + return S_OK; +} + +HRESULT ServiceController::InstallService(const string16& user, + const string16& password, + const std::string& run_switch, + const base::FilePath& user_data_dir) { + // TODO(vitalybuka): consider "lite" version if we don't want unregister + // printers here. + HRESULT hr = UninstallService(); + if (FAILED(hr)) + return hr; + + hr = UpdateRegistryAppId(true); + if (FAILED(hr)) + return hr; + + base::FilePath service_path; + CHECK(PathService::Get(base::FILE_EXE, &service_path)); + CommandLine command_line(service_path); + command_line.AppendSwitch(run_switch); + command_line.AppendSwitchPath(kUserDataDirSwitch, user_data_dir); + + LocalSecurityPolicy local_security_policy; + if (local_security_policy.Open()) { + if (!local_security_policy.IsPrivilegeSet(user, kSeServiceLogonRight)) { + LOG(WARNING) << "Setting " << kSeServiceLogonRight << " for " << user; + if (!local_security_policy.SetPrivilege(user, kSeServiceLogonRight)) { + LOG(ERROR) << "Failed to set" << kSeServiceLogonRight; + LOG(ERROR) << "Make sure you can run the service as " << user << "."; + } + } + } else { + LOG(ERROR) << "Failed to open security policy."; + } + + ServiceHandle scm; + hr = OpenServiceManager(&scm); + if (FAILED(hr)) + return hr; + + ServiceHandle service( + ::CreateService( + scm, name_.c_str(), name_.c_str(), SERVICE_ALL_ACCESS, + SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, + command_line.GetCommandLineString().c_str(), NULL, NULL, NULL, + user.empty() ? NULL : user.c_str(), + password.empty() ? NULL : password.c_str())); + + if (!service.IsValid()) { + LOG(ERROR) << "Failed to install service as " << user << "."; + return HResultFromLastError(); + } + + return S_OK; +} + +HRESULT ServiceController::UninstallService() { + StopService(); + + ServiceHandle service; + OpenService(name_, SERVICE_STOP | DELETE, &service); + HRESULT hr = S_FALSE; + if (service) { + if (!::DeleteService(service)) { + LOG(ERROR) << "Failed to uninstall service"; + hr = HResultFromLastError(); + } + } + UpdateRegistryAppId(false); + return hr; +} + diff --git a/cloud_print/service/win/service_controller.h b/cloud_print/service/win/service_controller.h new file mode 100644 index 0000000..4e06059 --- /dev/null +++ b/cloud_print/service/win/service_controller.h @@ -0,0 +1,41 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CLOUD_PRINT_SERVICE_SERVICE_CONTROLLER_H_ +#define CLOUD_PRINT_SERVICE_SERVICE_CONTROLLER_H_ + +#include <atlbase.h> +#include <string> + +#include "base/string16.h" +#include "cloud_print/service/win/resource.h" + +namespace base { +class FilePath; +} // base + +class ServiceController { + public: + DECLARE_REGISTRY_APPID_RESOURCEID(IDR_CLOUDPRINTSERVICE, + "{8013FB7C-2E3E-4992-B8BD-05C0C4AB0627}") + + explicit ServiceController(const string16& name); + ~ServiceController(); + + HRESULT InstallService(const string16& user, + const string16& password, + const std::string& run_switch, + const base::FilePath& user_data_dir); + + HRESULT UninstallService(); + + HRESULT StartService(); + HRESULT StopService(); + + private: + const string16 name_; +}; + +#endif // CLOUD_PRINT_SERVICE_SERVICE_CONTROLLER_H_ + |