| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "cloud_print/service/win/cloud_print_service.h" | 5 #include "cloud_print/service/win/cloud_print_service.h" |
| 6 | 6 |
| 7 #define SECURITY_WIN32 | 7 #define SECURITY_WIN32 |
| 8 #include <security.h> | 8 #include <security.h> |
| 9 | 9 |
| 10 #include <iomanip> | 10 #include <iomanip> |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 #include "chrome/installer/launcher_support/chrome_launcher_support.h" | 22 #include "chrome/installer/launcher_support/chrome_launcher_support.h" |
| 23 #include "cloud_print/service/service_state.h" | 23 #include "cloud_print/service/service_state.h" |
| 24 #include "cloud_print/service/service_switches.h" | 24 #include "cloud_print/service/service_switches.h" |
| 25 #include "cloud_print/service/win/chrome_launcher.h" | 25 #include "cloud_print/service/win/chrome_launcher.h" |
| 26 #include "cloud_print/service/win/local_security_policy.h" | 26 #include "cloud_print/service/win/local_security_policy.h" |
| 27 #include "cloud_print/service/win/resource.h" | 27 #include "cloud_print/service/win/resource.h" |
| 28 #include "printing/backend/print_backend.h" | 28 #include "printing/backend/print_backend.h" |
| 29 | 29 |
| 30 namespace { | 30 namespace { |
| 31 | 31 |
| 32 const wchar_t kPrintersFileName[] = L"printers.txt"; | 32 const char kChromeIsNotAvalible[] = "\nChrome is not available\n"; |
| 33 const char kChromeIsAvalible[] = "\nChrome is available\n"; |
| 34 const wchar_t kRequirementsFileName[] = L"cloud_print_service_requirements.txt"; |
| 33 const wchar_t kServiceStateFileName[] = L"Service State"; | 35 const wchar_t kServiceStateFileName[] = L"Service State"; |
| 34 | 36 |
| 35 // The traits class for Windows Service. | 37 // The traits class for Windows Service. |
| 36 class ServiceHandleTraits { | 38 class ServiceHandleTraits { |
| 37 public: | 39 public: |
| 38 typedef SC_HANDLE Handle; | 40 typedef SC_HANDLE Handle; |
| 39 | 41 |
| 40 // Closes the handle. | 42 // Closes the handle. |
| 41 static bool CloseHandle(Handle handle) { | 43 static bool CloseHandle(Handle handle) { |
| 42 return ::CloseServiceHandle(handle) != FALSE; | 44 return ::CloseServiceHandle(handle) != FALSE; |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 | 164 |
| 163 class CloudPrintServiceModule | 165 class CloudPrintServiceModule |
| 164 : public ATL::CAtlServiceModuleT<CloudPrintServiceModule, IDS_SERVICENAME> { | 166 : public ATL::CAtlServiceModuleT<CloudPrintServiceModule, IDS_SERVICENAME> { |
| 165 public: | 167 public: |
| 166 typedef ATL::CAtlServiceModuleT<CloudPrintServiceModule, | 168 typedef ATL::CAtlServiceModuleT<CloudPrintServiceModule, |
| 167 IDS_SERVICENAME> Base; | 169 IDS_SERVICENAME> Base; |
| 168 | 170 |
| 169 DECLARE_REGISTRY_APPID_RESOURCEID(IDR_CLOUDPRINTSERVICE, | 171 DECLARE_REGISTRY_APPID_RESOURCEID(IDR_CLOUDPRINTSERVICE, |
| 170 "{8013FB7C-2E3E-4992-B8BD-05C0C4AB0627}") | 172 "{8013FB7C-2E3E-4992-B8BD-05C0C4AB0627}") |
| 171 | 173 |
| 172 CloudPrintServiceModule() : detect_printers_(false) { | 174 CloudPrintServiceModule() : check_requirements_(false) { |
| 173 } | 175 } |
| 174 | 176 |
| 175 HRESULT InitializeSecurity() { | 177 HRESULT InitializeSecurity() { |
| 176 // TODO(gene): Check if we need to call CoInitializeSecurity and provide | 178 // TODO(gene): Check if we need to call CoInitializeSecurity and provide |
| 177 // the appropriate security settings for service. | 179 // the appropriate security settings for service. |
| 178 return S_OK; | 180 return S_OK; |
| 179 } | 181 } |
| 180 | 182 |
| 181 HRESULT InstallService(const string16& user, | 183 HRESULT InstallService(const string16& user, |
| 182 const string16& password, | 184 const string16& password, |
| 183 const char* run_switch) { | 185 const char* run_switch) { |
| 184 using namespace chrome_launcher_support; | |
| 185 | |
| 186 // TODO(vitalybuka): consider "lite" version if we don't want unregister | 186 // TODO(vitalybuka): consider "lite" version if we don't want unregister |
| 187 // printers here. | 187 // printers here. |
| 188 HRESULT hr = UninstallService(); | 188 HRESULT hr = UninstallService(); |
| 189 if (FAILED(hr)) | 189 if (FAILED(hr)) |
| 190 return hr; | 190 return hr; |
| 191 | 191 |
| 192 if (GetChromePathForInstallationLevel(SYSTEM_LEVEL_INSTALLATION).empty()) { | |
| 193 LOG(WARNING) << "Found no Chrome installed for all users."; | |
| 194 } | |
| 195 | |
| 196 hr = UpdateRegistryAppId(true); | 192 hr = UpdateRegistryAppId(true); |
| 197 if (FAILED(hr)) | 193 if (FAILED(hr)) |
| 198 return hr; | 194 return hr; |
| 199 | 195 |
| 200 FilePath service_path; | 196 FilePath service_path; |
| 201 CHECK(PathService::Get(base::FILE_EXE, &service_path)); | 197 CHECK(PathService::Get(base::FILE_EXE, &service_path)); |
| 202 CommandLine command_line(service_path); | 198 CommandLine command_line(service_path); |
| 203 command_line.AppendSwitch(run_switch); | 199 command_line.AppendSwitch(run_switch); |
| 204 command_line.AppendSwitchPath(kUserDataDirSwitch, user_data_dir_); | 200 command_line.AppendSwitchPath(kUserDataDirSwitch, user_data_dir_); |
| 205 | 201 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 255 std::setbase(16) << *pnRetCode; | 251 std::setbase(16) << *pnRetCode; |
| 256 } | 252 } |
| 257 return is_service; | 253 return is_service; |
| 258 } | 254 } |
| 259 | 255 |
| 260 HRESULT PreMessageLoop(int nShowCmd) { | 256 HRESULT PreMessageLoop(int nShowCmd) { |
| 261 HRESULT hr = Base::PreMessageLoop(nShowCmd); | 257 HRESULT hr = Base::PreMessageLoop(nShowCmd); |
| 262 if (FAILED(hr)) | 258 if (FAILED(hr)) |
| 263 return hr; | 259 return hr; |
| 264 | 260 |
| 265 if (detect_printers_) { | 261 if (check_requirements_) { |
| 266 hr = DetectPrinters(); | 262 hr = CheckRequirements(); |
| 267 if (FAILED(hr)) | 263 if (FAILED(hr)) |
| 268 return hr; | 264 return hr; |
| 269 // Don't run message loop and stop service. | 265 // Don't run message loop and stop service. |
| 270 return S_FALSE; | 266 return S_FALSE; |
| 271 } else { | 267 } else { |
| 272 hr = StartConnector(); | 268 hr = StartConnector(); |
| 273 if (FAILED(hr)) | 269 if (FAILED(hr)) |
| 274 return hr; | 270 return hr; |
| 275 } | 271 } |
| 276 | 272 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 if (SUCCEEDED(hr) && command_line.HasSwitch(kStartSwitch)) | 313 if (SUCCEEDED(hr) && command_line.HasSwitch(kStartSwitch)) |
| 318 return StartService(); | 314 return StartService(); |
| 319 | 315 |
| 320 return hr; | 316 return hr; |
| 321 } | 317 } |
| 322 | 318 |
| 323 if (command_line.HasSwitch(kStartSwitch)) | 319 if (command_line.HasSwitch(kStartSwitch)) |
| 324 return StartService(); | 320 return StartService(); |
| 325 | 321 |
| 326 if (command_line.HasSwitch(kServiceSwitch) || | 322 if (command_line.HasSwitch(kServiceSwitch) || |
| 327 command_line.HasSwitch(kPrintersSwitch)) { | 323 command_line.HasSwitch(kRequirementsSwitch)) { |
| 328 *is_service = true; | 324 *is_service = true; |
| 329 detect_printers_ = command_line.HasSwitch(kPrintersSwitch); | 325 check_requirements_ = command_line.HasSwitch(kRequirementsSwitch); |
| 330 return S_OK; | 326 return S_OK; |
| 331 } | 327 } |
| 332 | 328 |
| 333 if (command_line.HasSwitch(kConsoleSwitch)) { | 329 if (command_line.HasSwitch(kConsoleSwitch)) { |
| 334 ::SetConsoleCtrlHandler(&ConsoleCtrlHandler, TRUE); | 330 ::SetConsoleCtrlHandler(&ConsoleCtrlHandler, TRUE); |
| 335 HRESULT hr = Run(); | 331 HRESULT hr = Run(); |
| 336 ::SetConsoleCtrlHandler(NULL, FALSE); | 332 ::SetConsoleCtrlHandler(NULL, FALSE); |
| 337 return hr; | 333 return hr; |
| 338 } | 334 } |
| 339 | 335 |
| 340 InvalidUsage(); | 336 InvalidUsage(); |
| 341 return S_FALSE; | 337 return S_FALSE; |
| 342 } | 338 } |
| 343 | 339 |
| 344 void SelectWindowsAccount(string16* run_as_user, | 340 void SelectWindowsAccount(string16* run_as_user, |
| 345 string16* run_as_password) { | 341 string16* run_as_password) { |
| 346 *run_as_user = GetCurrentUserName(); | 342 *run_as_user = GetCurrentUserName(); |
| 347 for (;;) { | 343 for (;;) { |
| 348 std::cout << "\nPlease provide Windows account to run service.\n"; | 344 std::cout << "\nPlease provide Windows account to run service.\n"; |
| 349 *run_as_user = ASCIIToWide(GetOption("Account as DOMAIN\\USERNAME", | 345 *run_as_user = ASCIIToWide(GetOption("Account as DOMAIN\\USERNAME", |
| 350 WideToASCII(*run_as_user), false)); | 346 WideToASCII(*run_as_user), false)); |
| 351 *run_as_password = ASCIIToWide(GetOption("Password", "", true)); | 347 *run_as_password = ASCIIToWide(GetOption("Password", "", true)); |
| 352 | 348 |
| 353 FilePath printers_filename(user_data_dir_); | 349 FilePath requirements_filename(user_data_dir_); |
| 354 printers_filename = printers_filename.Append(kPrintersFileName); | 350 requirements_filename = |
| 351 requirements_filename.Append(kRequirementsFileName); |
| 355 | 352 |
| 356 file_util::Delete(printers_filename, false); | 353 file_util::Delete(requirements_filename, false); |
| 354 if (file_util::PathExists(requirements_filename)) { |
| 355 LOG(ERROR) << "Unable to delete " << |
| 356 requirements_filename.value() << "."; |
| 357 continue; |
| 358 } |
| 357 if (FAILED(InstallService(run_as_user->c_str(), | 359 if (FAILED(InstallService(run_as_user->c_str(), |
| 358 run_as_password->c_str(), | 360 run_as_password->c_str(), |
| 359 kPrintersSwitch))) { | 361 kRequirementsSwitch))) { |
| 360 continue; | 362 continue; |
| 361 } | 363 } |
| 362 if (FAILED(StartService())) { | 364 bool service_started = SUCCEEDED(StartService()); |
| 365 UninstallService(); |
| 366 if (!service_started) { |
| 363 LOG(ERROR) << "Failed to start service as " << *run_as_user << "."; | 367 LOG(ERROR) << "Failed to start service as " << *run_as_user << "."; |
| 364 continue; | 368 continue; |
| 365 } | 369 } |
| 366 UninstallService(); | 370 std::string printers; |
| 367 if (!file_util::PathExists(printers_filename)) { | 371 if (!file_util::PathExists(requirements_filename) || |
| 368 LOG(ERROR) << "Service can't create " << printers_filename.value(); | 372 !file_util::ReadFileToString(requirements_filename, &printers)) { |
| 373 LOG(ERROR) << "Service can't create " << requirements_filename.value(); |
| 369 continue; | 374 continue; |
| 370 } | 375 } |
| 371 | 376 |
| 372 std::string printers; | 377 if (EndsWith(printers, kChromeIsNotAvalible, true)) { |
| 373 file_util::ReadFileToString(printers_filename, &printers); | 378 LOG(ERROR) << kChromeIsNotAvalible << " for " << *run_as_user << "."; |
| 374 std::cout << "\nPrinters available for " << run_as_user << ":\n"; | 379 continue; |
| 380 } |
| 381 |
| 382 std::cout << "\nService requirements check result: \n"; |
| 375 std::cout << printers << "\n"; | 383 std::cout << printers << "\n"; |
| 376 file_util::Delete(printers_filename, false); | 384 file_util::Delete(requirements_filename, false); |
| 377 | 385 |
| 378 if (AskUser("Do you want to use " + WideToASCII(*run_as_user) + "?")) | 386 if (AskUser("Do you want to use " + WideToASCII(*run_as_user) + "?")) |
| 379 return; | 387 return; |
| 380 } | 388 } |
| 381 } | 389 } |
| 382 | 390 |
| 383 HRESULT SetupServiceState() { | 391 HRESULT SetupServiceState() { |
| 384 FilePath file = user_data_dir_.Append(kServiceStateFileName); | 392 FilePath file = user_data_dir_.Append(kServiceStateFileName); |
| 385 | 393 |
| 386 for (;;) { | 394 for (;;) { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 SERVICE_STATUS status = {0}; | 484 SERVICE_STATUS status = {0}; |
| 477 if (!::ControlService(service, SERVICE_CONTROL_STOP, &status)) | 485 if (!::ControlService(service, SERVICE_CONTROL_STOP, &status)) |
| 478 return HResultFromLastError(); | 486 return HResultFromLastError(); |
| 479 while (::QueryServiceStatus(service, &status) && | 487 while (::QueryServiceStatus(service, &status) && |
| 480 status.dwCurrentState > SERVICE_STOPPED) { | 488 status.dwCurrentState > SERVICE_STOPPED) { |
| 481 Sleep(500); | 489 Sleep(500); |
| 482 } | 490 } |
| 483 return S_OK; | 491 return S_OK; |
| 484 } | 492 } |
| 485 | 493 |
| 486 HRESULT DetectPrinters() { | 494 HRESULT CheckRequirements() { |
| 487 FilePath printers_filename(user_data_dir_); | 495 FilePath requirements_filename(user_data_dir_); |
| 488 printers_filename = printers_filename.Append(kPrintersFileName); | 496 requirements_filename = requirements_filename.Append(kRequirementsFileName); |
| 489 std::string printers; | 497 std::string output; |
| 498 output.append("Printers available for " + |
| 499 WideToASCII(GetCurrentUserName()) + ":\n"); |
| 490 scoped_refptr<printing::PrintBackend> backend( | 500 scoped_refptr<printing::PrintBackend> backend( |
| 491 printing::PrintBackend::CreateInstance(NULL)); | 501 printing::PrintBackend::CreateInstance(NULL)); |
| 492 printing::PrinterList printer_list; | 502 printing::PrinterList printer_list; |
| 493 backend->EnumeratePrinters(&printer_list); | 503 backend->EnumeratePrinters(&printer_list); |
| 494 for (size_t i = 0; i < printer_list.size(); ++i) { | 504 for (size_t i = 0; i < printer_list.size(); ++i) { |
| 495 printers += printer_list[i].printer_name; | 505 output += " "; |
| 496 printers += "\n"; | 506 output += printer_list[i].printer_name; |
| 507 output += "\n"; |
| 497 } | 508 } |
| 498 file_util::WriteFile(printers_filename, printers.c_str(), printers.size()); | 509 FilePath chrome = chrome_launcher_support::GetAnyChromePath(); |
| 510 output.append(chrome.empty() ? kChromeIsNotAvalible : kChromeIsAvalible); |
| 511 file_util::WriteFile(requirements_filename, output.c_str(), output.size()); |
| 499 return S_OK; | 512 return S_OK; |
| 500 } | 513 } |
| 501 | 514 |
| 502 HRESULT StartConnector() { | 515 HRESULT StartConnector() { |
| 503 chrome_.reset(new ChromeLauncher(user_data_dir_)); | 516 chrome_.reset(new ChromeLauncher(user_data_dir_)); |
| 504 return chrome_->Start() ? S_OK : E_FAIL; | 517 return chrome_->Start() ? S_OK : E_FAIL; |
| 505 } | 518 } |
| 506 | 519 |
| 507 void StopConnector() { | 520 void StopConnector() { |
| 508 if (chrome_.get()) { | 521 if (chrome_.get()) { |
| 509 chrome_->Stop(); | 522 chrome_->Stop(); |
| 510 chrome_.reset(); | 523 chrome_.reset(); |
| 511 } | 524 } |
| 512 } | 525 } |
| 513 | 526 |
| 514 static BOOL WINAPI ConsoleCtrlHandler(DWORD type); | 527 static BOOL WINAPI ConsoleCtrlHandler(DWORD type); |
| 515 | 528 |
| 516 bool detect_printers_; | 529 bool check_requirements_; |
| 517 FilePath user_data_dir_; | 530 FilePath user_data_dir_; |
| 518 scoped_ptr<ChromeLauncher> chrome_; | 531 scoped_ptr<ChromeLauncher> chrome_; |
| 519 }; | 532 }; |
| 520 | 533 |
| 521 CloudPrintServiceModule _AtlModule; | 534 CloudPrintServiceModule _AtlModule; |
| 522 | 535 |
| 523 BOOL CloudPrintServiceModule::ConsoleCtrlHandler(DWORD type) { | 536 BOOL CloudPrintServiceModule::ConsoleCtrlHandler(DWORD type) { |
| 524 PostThreadMessage(_AtlModule.m_dwThreadID, WM_QUIT, 0, 0); | 537 PostThreadMessage(_AtlModule.m_dwThreadID, WM_QUIT, 0, 0); |
| 525 return TRUE; | 538 return TRUE; |
| 526 } | 539 } |
| 527 | 540 |
| 528 int main() { | 541 int main() { |
| 529 base::AtExitManager at_exit; | 542 base::AtExitManager at_exit; |
| 530 return _AtlModule.WinMain(0); | 543 return _AtlModule.WinMain(0); |
| 531 } | 544 } |
| OLD | NEW |