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