1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "cloud_print/service/win/installer.h" 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <winerror.h> 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/at_exit.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/command_line.h" 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/file_util.h" 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/path_service.h" 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/win/scoped_com_initializer.h" 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/win/shortcut.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "cloud_print/common/win/cloud_print_utils.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "cloud_print/common/win/install_utils.h" 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "cloud_print/resources.h" 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "cloud_print/service/service_constants.h" 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "cloud_print/service/service_switches.h" 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "cloud_print/service/win/service_controller.h" 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const wchar_t kConfigBinaryName[] = L"cloud_print_service_config.exe"; 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::FilePath GetShortcutPath(int dir_key, bool with_subdir) { 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath path; 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!PathService::Get(dir_key, &path)) 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return base::FilePath(); 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) path = path.Append(cloud_print::LoadLocalString(IDS_FULL_PRODUCT_NAME)); 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (with_subdir) 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) path = path.Append(cloud_print::LoadLocalString(IDS_FULL_PRODUCT_NAME)); 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return path.InsertBeforeExtension(L".lnk"); 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CreateShortcut(int dir_key, bool with_subdir, 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::win::ShortcutOperation operation) { 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath path = GetShortcutPath(dir_key, with_subdir); 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (path.empty()) 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) file_util::CreateDirectory(path.DirName()); 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::win::ShortcutProperties properties; 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath exe_path; 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!PathService::Get(base::FILE_EXE, &exe_path)) 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) exe_path = exe_path.DirName().Append(base::FilePath(kConfigBinaryName)); 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) properties.set_target(exe_path); 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) properties.set_working_dir(exe_path.DirName()); 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CreateOrUpdateShortcutLink(path, properties, operation); 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CreateShortcuts(bool create_always) { 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::win::ScopedCOMInitializer co_init; 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::win::ShortcutOperation operation = 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) create_always ? base::win::SHORTCUT_CREATE_ALWAYS : 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::win::SHORTCUT_REPLACE_EXISTING; 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CreateShortcut(base::DIR_COMMON_START_MENU, true, operation); 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CreateShortcut(base::DIR_COMMON_DESKTOP, false, operation); 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DeleteShortcut(int dir_key, bool with_subdir) { 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath path = GetShortcutPath(dir_key, with_subdir); 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (path.empty()) 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (with_subdir) 677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::DeleteFile(path.DirName(), true); 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) else 697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::DeleteFile(path, false); 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DeleteShortcuts() { 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DeleteShortcut(base::DIR_COMMON_START_MENU, true); 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DeleteShortcut(base::DIR_COMMON_DESKTOP, false); 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)HRESULT ProcessInstallerSwitches() { 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const CommandLine& command_line(*CommandLine::ForCurrentProcess()); 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (command_line.HasSwitch(kInstallSwitch)) { 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath old_location = 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cloud_print::GetInstallLocation(kGoogleUpdateId); 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cloud_print::CreateUninstallKey( 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kGoogleUpdateId, cloud_print::LoadLocalString(IDS_FULL_PRODUCT_NAME), 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kUninstallSwitch); 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ServiceController controller; 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) HRESULT hr = controller.UpdateBinaryPath(); 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (FAILED(hr)) 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return hr; 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!old_location.empty() && 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cloud_print::IsProgramsFilesParent(old_location) && 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) old_location != cloud_print::GetInstallLocation(kGoogleUpdateId)) { 987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::DeleteFile(old_location, true); 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cloud_print::SetGoogleUpdateKeys( 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kGoogleUpdateId, cloud_print::LoadLocalString(IDS_FULL_PRODUCT_NAME)); 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CreateShortcuts(old_location.empty()); 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return S_OK; 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else if (command_line.HasSwitch(kUninstallSwitch)) { 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ServiceController controller; 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) HRESULT hr = controller.UninstallService(); 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (FAILED(hr)) 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return hr; 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DeleteShortcuts(); 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cloud_print::DeleteGoogleUpdateKeys(kGoogleUpdateId); 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cloud_print::DeleteUninstallKey(kGoogleUpdateId); 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cloud_print::DeleteProgramDir(kDeleteSwitch); 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return S_OK; 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else if (command_line.HasSwitch(kDeleteSwitch)) { 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath delete_path = command_line.GetSwitchValuePath(kDeleteSwitch); 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!delete_path.empty() && 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cloud_print::IsProgramsFilesParent(delete_path)) { 1237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::DeleteFile(delete_path, true); 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return S_OK; 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return S_FALSE; 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class CloudPrintServiceSetupModule 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : public ATL::CAtlExeModuleT<CloudPrintServiceSetupModule> { 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)CloudPrintServiceSetupModule _AtlModule; 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int WINAPI WinMain(__in HINSTANCE hInstance, 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) __in HINSTANCE hPrevInstance, 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) __in LPSTR lpCmdLine, 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) __in int nCmdShow) { 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::AtExitManager at_exit; 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CommandLine::Init(0, NULL); 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ProcessInstallerSwitches(); 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 145