// Copyright 2013 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/installer.h" #include #include "base/at_exit.h" #include "base/command_line.h" #include "base/file_util.h" #include "base/path_service.h" #include "base/win/scoped_com_initializer.h" #include "base/win/shortcut.h" #include "cloud_print/common/win/cloud_print_utils.h" #include "cloud_print/common/win/install_utils.h" #include "cloud_print/resources.h" #include "cloud_print/service/service_constants.h" #include "cloud_print/service/service_switches.h" #include "cloud_print/service/win/service_controller.h" namespace { const wchar_t kConfigBinaryName[] = L"cloud_print_service_config.exe"; base::FilePath GetShortcutPath(int dir_key, bool with_subdir) { base::FilePath path; if (!PathService::Get(dir_key, &path)) return base::FilePath(); path = path.Append(cloud_print::LoadLocalString(IDS_FULL_PRODUCT_NAME)); if (with_subdir) path = path.Append(cloud_print::LoadLocalString(IDS_FULL_PRODUCT_NAME)); return path.InsertBeforeExtension(L".lnk"); } void CreateShortcut(int dir_key, bool with_subdir, base::win::ShortcutOperation operation) { base::FilePath path = GetShortcutPath(dir_key, with_subdir); if (path.empty()) return; file_util::CreateDirectory(path.DirName()); base::win::ShortcutProperties properties; base::FilePath exe_path; if (!PathService::Get(base::FILE_EXE, &exe_path)) return; exe_path = exe_path.DirName().Append(base::FilePath(kConfigBinaryName)); properties.set_target(exe_path); properties.set_working_dir(exe_path.DirName()); CreateOrUpdateShortcutLink(path, properties, operation); } void CreateShortcuts(bool create_always) { base::win::ScopedCOMInitializer co_init; base::win::ShortcutOperation operation = create_always ? base::win::SHORTCUT_CREATE_ALWAYS : base::win::SHORTCUT_REPLACE_EXISTING; CreateShortcut(base::DIR_COMMON_START_MENU, true, operation); CreateShortcut(base::DIR_COMMON_DESKTOP, false, operation); } void DeleteShortcut(int dir_key, bool with_subdir) { base::FilePath path = GetShortcutPath(dir_key, with_subdir); if (path.empty()) return; if (with_subdir) base::DeleteFile(path.DirName(), true); else base::DeleteFile(path, false); } void DeleteShortcuts() { DeleteShortcut(base::DIR_COMMON_START_MENU, true); DeleteShortcut(base::DIR_COMMON_DESKTOP, false); } } // namespace HRESULT ProcessInstallerSwitches() { const CommandLine& command_line(*CommandLine::ForCurrentProcess()); if (command_line.HasSwitch(kInstallSwitch)) { base::FilePath old_location = cloud_print::GetInstallLocation(kGoogleUpdateId); cloud_print::CreateUninstallKey( kGoogleUpdateId, cloud_print::LoadLocalString(IDS_FULL_PRODUCT_NAME), kUninstallSwitch); ServiceController controller; HRESULT hr = controller.UpdateBinaryPath(); if (FAILED(hr)) return hr; if (!old_location.empty() && cloud_print::IsProgramsFilesParent(old_location) && old_location != cloud_print::GetInstallLocation(kGoogleUpdateId)) { base::DeleteFile(old_location, true); } cloud_print::SetGoogleUpdateKeys( kGoogleUpdateId, cloud_print::LoadLocalString(IDS_FULL_PRODUCT_NAME)); CreateShortcuts(old_location.empty()); return S_OK; } else if (command_line.HasSwitch(kUninstallSwitch)) { ServiceController controller; HRESULT hr = controller.UninstallService(); if (FAILED(hr)) return hr; DeleteShortcuts(); cloud_print::DeleteGoogleUpdateKeys(kGoogleUpdateId); cloud_print::DeleteUninstallKey(kGoogleUpdateId); cloud_print::DeleteProgramDir(kDeleteSwitch); return S_OK; } else if (command_line.HasSwitch(kDeleteSwitch)) { base::FilePath delete_path = command_line.GetSwitchValuePath(kDeleteSwitch); if (!delete_path.empty() && cloud_print::IsProgramsFilesParent(delete_path)) { base::DeleteFile(delete_path, true); } return S_OK; } return S_FALSE; } class CloudPrintServiceSetupModule : public ATL::CAtlExeModuleT { }; CloudPrintServiceSetupModule _AtlModule; int WINAPI WinMain(__in HINSTANCE hInstance, __in HINSTANCE hPrevInstance, __in LPSTR lpCmdLine, __in int nCmdShow) { base::AtExitManager at_exit; CommandLine::Init(0, NULL); return ProcessInstallerSwitches(); }