diff options
author | dmikurube@chromium.org <dmikurube@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-10 17:24:43 +0000 |
---|---|---|
committer | dmikurube@chromium.org <dmikurube@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-10 17:24:43 +0000 |
commit | a1585c8a0f44984ca749da4efeb9692ec43fa902 (patch) | |
tree | eab59c80bb1fc88510ab57d85c762943e3f4a008 /cloud_print/service/win/cloud_print_service.cc | |
parent | dc36652445cd10ed624c65fbe1c8b93356ca3922 (diff) | |
download | chromium_src-a1585c8a0f44984ca749da4efeb9692ec43fa902.zip chromium_src-a1585c8a0f44984ca749da4efeb9692ec43fa902.tar.gz chromium_src-a1585c8a0f44984ca749da4efeb9692ec43fa902.tar.bz2 |
Revert 187205 - Exctracted ServiceController.
It looks like caused the following "compile error".
http://build.chromium.org/p/chromium.win/builders/Win%20x64%20Builder/builds/1363/steps/compile/logs/stdio
FAILED: C:\b\depot_tools\python_bin\python.exe gyp-win-tool rc-wrapper environment.x64 rc.exe ... ..\..\cloud_print\service\win\cloud_print_service.rc
..\..\cloud_print\service\win\cloud_print_service.rc(13) : fatal error RC1015: cannot open include file 'version.h'.
BUG=0
TBR=gene
Review URL: https://chromiumcodereview.appspot.com/12412017
TBR=vitalybuka@chromium.org
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@187213 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cloud_print/service/win/cloud_print_service.cc')
-rw-r--r-- | cloud_print/service/win/cloud_print_service.cc | 559 |
1 files changed, 359 insertions, 200 deletions
diff --git a/cloud_print/service/win/cloud_print_service.cc b/cloud_print/service/win/cloud_print_service.cc index 32f7c91..b22c603 100644 --- a/cloud_print/service/win/cloud_print_service.cc +++ b/cloud_print/service/win/cloud_print_service.cc @@ -4,23 +4,27 @@ #include "cloud_print/service/win/cloud_print_service.h" +#define SECURITY_WIN32 #include <security.h> #include <iomanip> #include <iostream> +#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/service_controller.h" +#include "cloud_print/service/win/local_security_policy.h" +#include "cloud_print/service/win/resource.h" #include "printing/backend/print_backend.h" namespace { @@ -30,6 +34,39 @@ 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)); @@ -125,261 +162,383 @@ string16 GetCurrentUserName() { } // namespace -CloudPrintService::CloudPrintService() - : check_requirements_(false), - controller_(new ServiceController(m_szServiceName)) { -} - -CloudPrintService::~CloudPrintService() { -} - -wchar_t* CloudPrintService::GetAppIdT() { - return ServiceController::GetAppIdT(); -}; +class CloudPrintServiceModule + : public ATL::CAtlServiceModuleT<CloudPrintServiceModule, IDS_SERVICENAME> { + public: + typedef ATL::CAtlServiceModuleT<CloudPrintServiceModule, + IDS_SERVICENAME> Base; -HRESULT CloudPrintService::InitializeSecurity() { - // TODO(gene): Check if we need to call CoInitializeSecurity and provide - // the appropriate security settings for service. - return S_OK; -} + DECLARE_REGISTRY_APPID_RESOURCEID(IDR_CLOUDPRINTSERVICE, + "{8013FB7C-2E3E-4992-B8BD-05C0C4AB0627}") -bool CloudPrintService::ParseCommandLine(LPCTSTR lpCmdLine, - HRESULT* pnRetCode) { - CHECK(pnRetCode); - CommandLine command_line(CommandLine::NO_PROGRAM); - command_line.ParseFromString(lpCmdLine); - bool is_service = false; - *pnRetCode = ParseCommandLine(command_line, &is_service); - if (FAILED(*pnRetCode)) { - LOG(ERROR) << "Operation failed. 0x" << std::setw(8) << - std::setbase(16) << *pnRetCode; + CloudPrintServiceModule() : check_requirements_(false) { } - return is_service; -} -HRESULT CloudPrintService::PreMessageLoop(int nShowCmd) { - HRESULT hr = Base::PreMessageLoop(nShowCmd); - if (FAILED(hr)) - return hr; + HRESULT InitializeSecurity() { + // TODO(gene): Check if we need to call CoInitializeSecurity and provide + // the appropriate security settings for service. + return S_OK; + } - if (check_requirements_) { - hr = CheckRequirements(); + 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; - // Don't run message loop and stop service. - return S_FALSE; - } else { - hr = StartConnector(); + + hr = UpdateRegistryAppId(true); if (FAILED(hr)) return hr; - } - LogEvent(_T("Service started/resumed")); - SetServiceStatus(SERVICE_RUNNING); - - 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."; + } -HRESULT CloudPrintService::PostMessageLoop() { - StopConnector(); - return Base::PostMessageLoop(); -} + ServiceHandle scm; + hr = OpenServiceManager(&scm); + if (FAILED(hr)) + return hr; -HRESULT CloudPrintService::ParseCommandLine(const CommandLine& command_line, - bool* is_service) { - if (!is_service) - return E_INVALIDARG; - *is_service = false; + 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(); + } - user_data_dir_ = command_line.GetSwitchValuePath(kUserDataDirSwitch); - if (command_line.HasSwitch(kStopSwitch)) - return controller_->StopService(); + return S_OK; + } - if (command_line.HasSwitch(kUninstallSwitch)) - return controller_->UninstallService(); + HRESULT UninstallService() { + StopService(); + if (!Uninstall()) + return E_FAIL; + return UpdateRegistryAppId(false); + } - if (command_line.HasSwitch(kInstallSwitch)) { - if (!command_line.HasSwitch(kUserDataDirSwitch)) { - InvalidUsage(); - return S_FALSE; + bool ParseCommandLine(LPCTSTR lpCmdLine, HRESULT* pnRetCode) { + CHECK(pnRetCode); + CommandLine command_line(CommandLine::NO_PROGRAM); + command_line.ParseFromString(lpCmdLine); + bool is_service = false; + *pnRetCode = ParseCommandLine(command_line, &is_service); + if (FAILED(*pnRetCode)) { + LOG(ERROR) << "Operation failed. 0x" << std::setw(8) << + std::setbase(16) << *pnRetCode; } + return is_service; + } - string16 run_as_user; - string16 run_as_password; - SelectWindowsAccount(&run_as_user, &run_as_password); - - HRESULT hr = SetupServiceState(); + HRESULT PreMessageLoop(int nShowCmd) { + HRESULT hr = Base::PreMessageLoop(nShowCmd); if (FAILED(hr)) return hr; - hr = controller_->InstallService(run_as_user, run_as_password, - kServiceSwitch, user_data_dir_); - if (SUCCEEDED(hr) && command_line.HasSwitch(kStartSwitch)) - return controller_->StartService(); + if (check_requirements_) { + hr = CheckRequirements(); + if (FAILED(hr)) + return hr; + // Don't run message loop and stop service. + return S_FALSE; + } else { + hr = StartConnector(); + if (FAILED(hr)) + return hr; + } + + LogEvent(_T("Service started/resumed")); + SetServiceStatus(SERVICE_RUNNING); return hr; } - if (command_line.HasSwitch(kStartSwitch)) - return controller_->StartService(); - - if (command_line.HasSwitch(kServiceSwitch) || - command_line.HasSwitch(kRequirementsSwitch)) { - *is_service = true; - check_requirements_ = command_line.HasSwitch(kRequirementsSwitch); - return S_OK; + HRESULT PostMessageLoop() { + StopConnector(); + return Base::PostMessageLoop(); } - if (command_line.HasSwitch(kConsoleSwitch)) { - ::SetConsoleCtrlHandler(&ConsoleCtrlHandler, TRUE); - HRESULT hr = Run(); - ::SetConsoleCtrlHandler(NULL, FALSE); - return hr; - } + private: + HRESULT ParseCommandLine(const CommandLine& command_line, bool* is_service) { + if (!is_service) + return E_INVALIDARG; + *is_service = false; - InvalidUsage(); - return S_FALSE; -} + user_data_dir_ = command_line.GetSwitchValuePath(kUserDataDirSwitch); + if (command_line.HasSwitch(kStopSwitch)) + return StopService(); -void CloudPrintService::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)); - *run_as_password = ASCIIToWide(GetOption("Password", "", true)); + if (command_line.HasSwitch(kUninstallSwitch)) + return UninstallService(); - base::FilePath requirements_filename(user_data_dir_); - requirements_filename = - requirements_filename.Append(kRequirementsFileName); - - file_util::Delete(requirements_filename, false); - if (file_util::PathExists(requirements_filename)) { - LOG(ERROR) << "Unable to delete " << - requirements_filename.value() << "."; - continue; - } - if (FAILED(controller_->InstallService(*run_as_user, *run_as_password, - kRequirementsSwitch, - user_data_dir_))) { - continue; - } - bool service_started = SUCCEEDED(controller_->StartService()); - controller_->UninstallService(); - if (!service_started) { - LOG(ERROR) << "Failed to start service as " << *run_as_user << "."; - continue; + if (command_line.HasSwitch(kInstallSwitch)) { + if (!command_line.HasSwitch(kUserDataDirSwitch)) { + InvalidUsage(); + return S_FALSE; + } + + string16 run_as_user; + string16 run_as_password; + SelectWindowsAccount(&run_as_user, &run_as_password); + + HRESULT hr = SetupServiceState(); + if (FAILED(hr)) + return hr; + + hr = InstallService(run_as_user.c_str(), run_as_password.c_str(), + kServiceSwitch); + if (SUCCEEDED(hr) && command_line.HasSwitch(kStartSwitch)) + return StartService(); + + return hr; } - std::string printers; - if (!file_util::PathExists(requirements_filename) || - !file_util::ReadFileToString(requirements_filename, &printers)) { - LOG(ERROR) << "Service can't create " << requirements_filename.value(); - continue; + + if (command_line.HasSwitch(kStartSwitch)) + return StartService(); + + if (command_line.HasSwitch(kServiceSwitch) || + command_line.HasSwitch(kRequirementsSwitch)) { + *is_service = true; + check_requirements_ = command_line.HasSwitch(kRequirementsSwitch); + return S_OK; } - if (EndsWith(printers, kChromeIsNotAvalible, true)) { - LOG(ERROR) << kChromeIsNotAvalible << " for " << *run_as_user << "."; - continue; + if (command_line.HasSwitch(kConsoleSwitch)) { + ::SetConsoleCtrlHandler(&ConsoleCtrlHandler, TRUE); + HRESULT hr = Run(); + ::SetConsoleCtrlHandler(NULL, FALSE); + return hr; } - std::cout << "\nService requirements check result: \n"; - std::cout << printers << "\n"; - file_util::Delete(requirements_filename, false); + InvalidUsage(); + return S_FALSE; + } - if (AskUser("Do you want to use " + WideToASCII(*run_as_user) + "?")) - return; + 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)); + *run_as_password = ASCIIToWide(GetOption("Password", "", true)); + + base::FilePath requirements_filename(user_data_dir_); + requirements_filename = + requirements_filename.Append(kRequirementsFileName); + + file_util::Delete(requirements_filename, false); + if (file_util::PathExists(requirements_filename)) { + LOG(ERROR) << "Unable to delete " << + requirements_filename.value() << "."; + continue; + } + if (FAILED(InstallService(run_as_user->c_str(), + run_as_password->c_str(), + kRequirementsSwitch))) { + continue; + } + bool service_started = SUCCEEDED(StartService()); + UninstallService(); + if (!service_started) { + LOG(ERROR) << "Failed to start service as " << *run_as_user << "."; + continue; + } + std::string printers; + if (!file_util::PathExists(requirements_filename) || + !file_util::ReadFileToString(requirements_filename, &printers)) { + LOG(ERROR) << "Service can't create " << requirements_filename.value(); + continue; + } + + if (EndsWith(printers, kChromeIsNotAvalible, true)) { + LOG(ERROR) << kChromeIsNotAvalible << " for " << *run_as_user << "."; + continue; + } + + std::cout << "\nService requirements check result: \n"; + std::cout << printers << "\n"; + file_util::Delete(requirements_filename, false); + + if (AskUser("Do you want to use " + WideToASCII(*run_as_user) + "?")) + return; + } } -} -HRESULT CloudPrintService::SetupServiceState() { - base::FilePath file = user_data_dir_.Append(kServiceStateFileName); + HRESULT SetupServiceState() { + base::FilePath file = user_data_dir_.Append(kServiceStateFileName); - for (;;) { - std::string contents; - ServiceState service_state; + for (;;) { + std::string contents; + ServiceState service_state; - bool is_valid = file_util::ReadFileToString(file, &contents) && - service_state.FromString(contents); + bool is_valid = file_util::ReadFileToString(file, &contents) && + service_state.FromString(contents); - std::cout << "\nFile '" << file.value() << "' content:\n"; - std::cout << contents << "\n"; + std::cout << "\nFile '" << file.value() << "' content:\n"; + std::cout << contents << "\n"; - if (!is_valid) - LOG(ERROR) << "Invalid file: " << file.value(); + if (!is_valid) + LOG(ERROR) << "Invalid file: " << file.value(); - if (!contents.empty()) { - if (AskUser("Do you want to use '" + WideToASCII(file.value()) + "'")) { - return S_OK; - } else { - is_valid = false; + if (!contents.empty()) { + if (AskUser("Do you want to use '" + WideToASCII(file.value()) + "'")) { + return S_OK; + } else { + is_valid = false; + } } - } - while (!is_valid) { - std::cout << "\nPlease provide Cloud Print Settings.\n"; - std::string email = GetOption("email", service_state.email(), false); - std::string password = GetOption("password", "", true); - std::string proxy_id = service_state.proxy_id(); - if (proxy_id.empty()) - proxy_id = base::GenerateGUID(); - proxy_id = GetOption("connector_id", proxy_id, false); - is_valid = service_state.Configure(email, password, proxy_id); - if (is_valid) { - std::string new_contents = service_state.ToString(); - if (new_contents != contents) { - size_t written = file_util::WriteFile(file, new_contents.c_str(), - new_contents.size()); - if (written != new_contents.size()) { - LOG(ERROR) << "Failed to write file " << file.value() << "."; - HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); - if (SUCCEEDED(hr)) - return E_FAIL; - return hr; + while (!is_valid) { + std::cout << "\nPlease provide Cloud Print Settings.\n"; + std::string email = GetOption("email", service_state.email(), false); + std::string password = GetOption("password", "", true); + std::string proxy_id = service_state.proxy_id(); + if (proxy_id.empty()) + proxy_id = base::GenerateGUID(); + proxy_id = GetOption("connector_id", proxy_id, false); + is_valid = service_state.Configure(email, password, proxy_id); + if (is_valid) { + std::string new_contents = service_state.ToString(); + if (new_contents != contents) { + size_t written = file_util::WriteFile(file, new_contents.c_str(), + new_contents.size()); + if (written != new_contents.size()) { + LOG(ERROR) << "Failed to write file " << file.value() << "."; + return HResultFromLastError(); + } } } } } + + return S_OK; } - 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(); -void CloudPrintService::StopConnector() { - if (chrome_.get()) { - chrome_->Stop(); - chrome_.reset(); + return S_OK; } -} -HRESULT CloudPrintService::CheckRequirements() { - base::FilePath requirements_filename(user_data_dir_); - requirements_filename = requirements_filename.Append(kRequirementsFileName); - std::string output; - output.append("Printers available for " + - WideToASCII(GetCurrentUserName()) + ":\n"); - scoped_refptr<printing::PrintBackend> backend( - printing::PrintBackend::CreateInstance(NULL)); - printing::PrinterList printer_list; - backend->EnumeratePrinters(&printer_list); - for (size_t i = 0; i < printer_list.size(); ++i) { - output += " "; - output += printer_list[i].printer_name; - output += "\n"; + 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; } - base::FilePath chrome = chrome_launcher_support::GetAnyChromePath(); - output.append(chrome.empty() ? kChromeIsNotAvalible : kChromeIsAvalible); - file_util::WriteFile(requirements_filename, output.c_str(), output.size()); - return S_OK; -} -HRESULT CloudPrintService::StartConnector() { - chrome_.reset(new ChromeLauncher(user_data_dir_)); - return chrome_->Start() ? S_OK : E_FAIL; -} + 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; + } -BOOL CloudPrintService::ConsoleCtrlHandler(DWORD type) { + 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); + std::string output; + output.append("Printers available for " + + WideToASCII(GetCurrentUserName()) + ":\n"); + scoped_refptr<printing::PrintBackend> backend( + printing::PrintBackend::CreateInstance(NULL)); + printing::PrinterList printer_list; + backend->EnumeratePrinters(&printer_list); + for (size_t i = 0; i < printer_list.size(); ++i) { + output += " "; + output += printer_list[i].printer_name; + output += "\n"; + } + base::FilePath chrome = chrome_launcher_support::GetAnyChromePath(); + output.append(chrome.empty() ? kChromeIsNotAvalible : kChromeIsAvalible); + file_util::WriteFile(requirements_filename, output.c_str(), output.size()); + return S_OK; + } + + HRESULT StartConnector() { + chrome_.reset(new ChromeLauncher(user_data_dir_)); + return chrome_->Start() ? S_OK : E_FAIL; + } + + void StopConnector() { + if (chrome_.get()) { + chrome_->Stop(); + chrome_.reset(); + } + } + + static BOOL WINAPI ConsoleCtrlHandler(DWORD type); + + bool check_requirements_; + base::FilePath user_data_dir_; + scoped_ptr<ChromeLauncher> chrome_; +}; + +CloudPrintServiceModule _AtlModule; + +BOOL CloudPrintServiceModule::ConsoleCtrlHandler(DWORD type) { PostThreadMessage(_AtlModule.m_dwThreadID, WM_QUIT, 0, 0); return TRUE; } +int main() { + base::AtExitManager at_exit; + return _AtlModule.WinMain(0); +} |