summaryrefslogtreecommitdiffstats
path: root/cloud_print/service/win/cloud_print_service.cc
diff options
context:
space:
mode:
authordmikurube@chromium.org <dmikurube@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-10 17:24:43 +0000
committerdmikurube@chromium.org <dmikurube@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-10 17:24:43 +0000
commita1585c8a0f44984ca749da4efeb9692ec43fa902 (patch)
treeeab59c80bb1fc88510ab57d85c762943e3f4a008 /cloud_print/service/win/cloud_print_service.cc
parentdc36652445cd10ed624c65fbe1c8b93356ca3922 (diff)
downloadchromium_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.cc559
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);
+}