| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 <shlobj.h> | 5 #include <shlobj.h> |
| 6 #include <time.h> | 6 #include <time.h> |
| 7 | 7 |
| 8 #include "chrome/installer/setup/install.h" | 8 #include "chrome/installer/setup/install.h" |
| 9 | 9 |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 uninstall_cmd_line->append(installer_util::switches::kDeleteProfile); | 92 uninstall_cmd_line->append(installer_util::switches::kDeleteProfile); |
| 93 uninstall_cmd_line->append(L" --"); | 93 uninstall_cmd_line->append(L" --"); |
| 94 uninstall_cmd_line->append(installer_util::switches::kChromeFrame); | 94 uninstall_cmd_line->append(installer_util::switches::kChromeFrame); |
| 95 } | 95 } |
| 96 | 96 |
| 97 if (InstallUtil::IsChromeSxSProcess()) { | 97 if (InstallUtil::IsChromeSxSProcess()) { |
| 98 uninstall_cmd_line->append(L" --"); | 98 uninstall_cmd_line->append(L" --"); |
| 99 uninstall_cmd_line->append(installer_util::switches::kChromeSxS); | 99 uninstall_cmd_line->append(installer_util::switches::kChromeSxS); |
| 100 } | 100 } |
| 101 | 101 |
| 102 if (InstallUtil::IsMSIProcess()) { | 102 if (InstallUtil::IsMSIProcess(is_system)) { |
| 103 uninstall_cmd_line->append(L" --"); | 103 uninstall_cmd_line->append(L" --"); |
| 104 uninstall_cmd_line->append(installer_util::switches::kMsi); | 104 uninstall_cmd_line->append(installer_util::switches::kMsi); |
| 105 } | 105 } |
| 106 | 106 |
| 107 // Propagate the verbose logging switch to uninstalls too. | 107 // Propagate the verbose logging switch to uninstalls too. |
| 108 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | 108 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
| 109 if (command_line.HasSwitch(installer_util::switches::kVerboseLogging)) { | 109 if (command_line.HasSwitch(installer_util::switches::kVerboseLogging)) { |
| 110 uninstall_cmd_line->append(L" --"); | 110 uninstall_cmd_line->append(L" --"); |
| 111 uninstall_cmd_line->append(installer_util::switches::kVerboseLogging); | 111 uninstall_cmd_line->append(installer_util::switches::kVerboseLogging); |
| 112 } | 112 } |
| 113 | 113 |
| 114 if (is_system) { | 114 if (is_system) { |
| 115 uninstall_cmd_line->append(L" --"); | 115 uninstall_cmd_line->append(L" --"); |
| 116 uninstall_cmd_line->append(installer_util::switches::kSystemLevel); | 116 uninstall_cmd_line->append(installer_util::switches::kSystemLevel); |
| 117 } | 117 } |
| 118 } | 118 } |
| 119 | 119 |
| 120 // This method adds work items to create (or update) Chrome uninstall entry in | 120 // This method adds work items to create (or update) Chrome uninstall entry in |
| 121 // either the Control Panel->Add/Remove Programs list or in the Omaha client | 121 // either the Control Panel->Add/Remove Programs list or in the Omaha client |
| 122 // state key if running under an MSI installer. | 122 // state key if running under an MSI installer. |
| 123 void AddUninstallShortcutWorkItems(HKEY reg_root, | 123 void AddUninstallShortcutWorkItems(HKEY reg_root, |
| 124 const std::wstring& exe_path, | 124 const std::wstring& exe_path, |
| 125 const std::wstring& install_path, | 125 const std::wstring& install_path, |
| 126 const std::wstring& product_name, | 126 const std::wstring& product_name, |
| 127 const std::wstring& new_version, | 127 const std::wstring& new_version, |
| 128 WorkItemList* install_list) { | 128 WorkItemList* install_list) { |
| 129 std::wstring uninstall_cmd(L"\""); | |
| 130 uninstall_cmd.append(installer::GetInstallerPathUnderChrome(install_path, | |
| 131 new_version)); | |
| 132 file_util::AppendToPath(&uninstall_cmd, | |
| 133 file_util::GetFilenameFromPath(exe_path)); | |
| 134 uninstall_cmd.append(L"\""); | |
| 135 | |
| 136 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); | 129 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
| 137 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | 130 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
| 138 | 131 |
| 139 | |
| 140 // When we are installed via an MSI, we need to store our uninstall strings | 132 // When we are installed via an MSI, we need to store our uninstall strings |
| 141 // in the Google Update client state key. We do this even for non-MSI | 133 // in the Google Update client state key. We do this even for non-MSI |
| 142 // managed installs to avoid breaking the edge case whereby an MSI-managed | 134 // managed installs to avoid breaking the edge case whereby an MSI-managed |
| 143 // install is updated by a non-msi installer (which would confuse the MSI | 135 // install is updated by a non-msi installer (which would confuse the MSI |
| 144 // machinery if these strings were not also updated). | 136 // machinery if these strings were not also updated). |
| 137 // Do not quote the command line for the MSI invocation. |
| 138 std::wstring uninstall_cmd( |
| 139 installer::GetInstallerPathUnderChrome(install_path, new_version)); |
| 140 file_util::AppendToPath(&uninstall_cmd, |
| 141 file_util::GetFilenameFromPath(exe_path)); |
| 145 std::wstring uninstall_arguments; | 142 std::wstring uninstall_arguments; |
| 146 AppendUninstallCommandLineFlags(&uninstall_arguments, | 143 AppendUninstallCommandLineFlags(&uninstall_arguments, |
| 147 reg_root == HKEY_LOCAL_MACHINE); | 144 reg_root == HKEY_LOCAL_MACHINE); |
| 145 |
| 148 std::wstring update_state_key = dist->GetStateKey(); | 146 std::wstring update_state_key = dist->GetStateKey(); |
| 149 install_list->AddCreateRegKeyWorkItem(reg_root, update_state_key); | 147 install_list->AddCreateRegKeyWorkItem(reg_root, update_state_key); |
| 150 install_list->AddSetRegValueWorkItem(reg_root, update_state_key, | 148 install_list->AddSetRegValueWorkItem(reg_root, update_state_key, |
| 151 installer_util::kUninstallStringField, uninstall_cmd, true); | 149 installer_util::kUninstallStringField, uninstall_cmd, true); |
| 152 install_list->AddSetRegValueWorkItem(reg_root, update_state_key, | 150 install_list->AddSetRegValueWorkItem(reg_root, update_state_key, |
| 153 installer_util::kUninstallArgumentsField, uninstall_arguments, true); | 151 installer_util::kUninstallArgumentsField, uninstall_arguments, true); |
| 154 | 152 |
| 155 // MSI installations will manage their own uninstall shortcuts. | 153 // MSI installations will manage their own uninstall shortcuts. |
| 156 if (!InstallUtil::IsMSIProcess()) { | 154 if (!InstallUtil::IsMSIProcess(reg_root == HKEY_LOCAL_MACHINE)) { |
| 157 AppendUninstallCommandLineFlags(&uninstall_cmd, | 155 // We need to quote the command line for the Add/Remove Programs dialog. |
| 156 std::wstring quoted_uninstall_cmd(L"\""); |
| 157 quoted_uninstall_cmd += uninstall_cmd; |
| 158 quoted_uninstall_cmd += L"\""; |
| 159 |
| 160 AppendUninstallCommandLineFlags("ed_uninstall_cmd, |
| 158 reg_root == HKEY_LOCAL_MACHINE); | 161 reg_root == HKEY_LOCAL_MACHINE); |
| 159 std::wstring uninstall_reg = dist->GetUninstallRegPath(); | 162 std::wstring uninstall_reg = dist->GetUninstallRegPath(); |
| 160 install_list->AddCreateRegKeyWorkItem(reg_root, uninstall_reg); | 163 install_list->AddCreateRegKeyWorkItem(reg_root, uninstall_reg); |
| 161 install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg, | 164 install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg, |
| 162 installer_util::kUninstallDisplayNameField, product_name, true); | 165 installer_util::kUninstallDisplayNameField, product_name, true); |
| 163 install_list->AddSetRegValueWorkItem(reg_root, | 166 install_list->AddSetRegValueWorkItem(reg_root, |
| 164 uninstall_reg, | 167 uninstall_reg, |
| 165 installer_util::kUninstallStringField, | 168 installer_util::kUninstallStringField, |
| 166 uninstall_cmd, true); | 169 quoted_uninstall_cmd, |
| 170 true); |
| 167 install_list->AddSetRegValueWorkItem(reg_root, | 171 install_list->AddSetRegValueWorkItem(reg_root, |
| 168 uninstall_reg, | 172 uninstall_reg, |
| 169 L"InstallLocation", | 173 L"InstallLocation", |
| 170 install_path, | 174 install_path, |
| 171 true); | 175 true); |
| 172 | 176 |
| 173 // DisplayIcon, NoModify and NoRepair | 177 // DisplayIcon, NoModify and NoRepair |
| 174 std::wstring chrome_icon = AppendPath(install_path, | 178 std::wstring chrome_icon = AppendPath(install_path, |
| 175 installer_util::kChromeExe); | 179 installer_util::kChromeExe); |
| 176 ShellUtil::GetChromeIcon(chrome_icon); | 180 ShellUtil::GetChromeIcon(chrome_icon); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 chrome_link.value(), | 279 chrome_link.value(), |
| 276 product_desc, true); | 280 product_desc, true); |
| 277 } else if (file_util::PathExists(chrome_link)) { | 281 } else if (file_util::PathExists(chrome_link)) { |
| 278 LOG(INFO) << "Updating shortcut at " << chrome_link.value() | 282 LOG(INFO) << "Updating shortcut at " << chrome_link.value() |
| 279 << " to point to " << chrome_exe; | 283 << " to point to " << chrome_exe; |
| 280 ret = ret && ShellUtil::UpdateChromeShortcut(chrome_exe, | 284 ret = ret && ShellUtil::UpdateChromeShortcut(chrome_exe, |
| 281 chrome_link.value(), | 285 chrome_link.value(), |
| 282 product_desc, false); | 286 product_desc, false); |
| 283 } | 287 } |
| 284 | 288 |
| 285 // Create/update uninstall link | 289 // Create/update uninstall link if we are not an MSI install. MSI |
| 286 FilePath uninstall_link(shortcut_path); // Uninstall Chrome link | 290 // installations are, for the time being, managed only through the |
| 287 uninstall_link = uninstall_link.Append( | 291 // Add/Remove Programs dialog. |
| 288 dist->GetUninstallLinkName() + L".lnk"); | 292 // TODO(robertshield): We could add a shortcut to msiexec /X {GUID} here. |
| 289 if ((install_status == installer_util::FIRST_INSTALL_SUCCESS) || | 293 if (!InstallUtil::IsMSIProcess(system_install)) { |
| 290 (install_status == installer_util::INSTALL_REPAIRED) || | 294 FilePath uninstall_link(shortcut_path); // Uninstall Chrome link |
| 291 (file_util::PathExists(uninstall_link))) { | 295 uninstall_link = uninstall_link.Append( |
| 292 if (!file_util::PathExists(shortcut_path)) | 296 dist->GetUninstallLinkName() + L".lnk"); |
| 293 file_util::CreateDirectoryW(shortcut_path); | 297 if ((install_status == installer_util::FIRST_INSTALL_SUCCESS) || |
| 294 std::wstring setup_exe(installer::GetInstallerPathUnderChrome(install_path, | 298 (install_status == installer_util::INSTALL_REPAIRED) || |
| 295 new_version)); | 299 (file_util::PathExists(uninstall_link))) { |
| 296 file_util::AppendToPath(&setup_exe, | 300 if (!file_util::PathExists(shortcut_path)) |
| 297 file_util::GetFilenameFromPath(exe_path)); | 301 file_util::CreateDirectoryW(shortcut_path); |
| 302 std::wstring setup_exe(installer::GetInstallerPathUnderChrome( |
| 303 install_path, new_version)); |
| 304 file_util::AppendToPath(&setup_exe, |
| 305 file_util::GetFilenameFromPath(exe_path)); |
| 298 | 306 |
| 299 std::wstring arguments; | 307 std::wstring arguments; |
| 300 AppendUninstallCommandLineFlags(&arguments, system_install); | 308 AppendUninstallCommandLineFlags(&arguments, system_install); |
| 301 | 309 LOG(INFO) << "Creating/updating uninstall link at " |
| 302 LOG(INFO) << "Creating/updating uninstall link at " | 310 << uninstall_link.value(); |
| 303 << uninstall_link.value(); | 311 ret = ret && file_util::CreateShortcutLink(setup_exe.c_str(), |
| 304 ret = ret && file_util::CreateShortcutLink(setup_exe.c_str(), | 312 uninstall_link.value().c_str(), |
| 305 uninstall_link.value().c_str(), | 313 NULL, |
| 306 NULL, | 314 arguments.c_str(), |
| 307 arguments.c_str(), | 315 NULL, |
| 308 NULL, setup_exe.c_str(), 0, | 316 setup_exe.c_str(), |
| 309 NULL); | 317 0, |
| 318 NULL); |
| 319 } |
| 310 } | 320 } |
| 311 | 321 |
| 312 // Update Desktop and Quick Launch shortcuts. If --create-new-shortcuts | 322 // Update Desktop and Quick Launch shortcuts. If --create-new-shortcuts |
| 313 // is specified we want to create them, otherwise we update them only if | 323 // is specified we want to create them, otherwise we update them only if |
| 314 // they exist. | 324 // they exist. |
| 315 if (system_install) { | 325 if (system_install) { |
| 316 ret = ret && ShellUtil::CreateChromeDesktopShortcut(chrome_exe, | 326 ret = ret && ShellUtil::CreateChromeDesktopShortcut(chrome_exe, |
| 317 product_desc, ShellUtil::SYSTEM_LEVEL, alt_shortcut, | 327 product_desc, ShellUtil::SYSTEM_LEVEL, alt_shortcut, |
| 318 create_all_shortcut); | 328 create_all_shortcut); |
| 319 ret = ret && ShellUtil::CreateChromeQuickLaunchShortcut(chrome_exe, | 329 ret = ret && ShellUtil::CreateChromeQuickLaunchShortcut(chrome_exe, |
| 320 ShellUtil::CURRENT_USER | ShellUtil::SYSTEM_LEVEL, create_all_shortcut); | 330 ShellUtil::CURRENT_USER | ShellUtil::SYSTEM_LEVEL, create_all_shortcut); |
| 321 } else { | 331 } else { |
| 322 ret = ret && ShellUtil::CreateChromeDesktopShortcut(chrome_exe, | 332 ret = ret && ShellUtil::CreateChromeDesktopShortcut(chrome_exe, |
| 323 product_desc, ShellUtil::CURRENT_USER, alt_shortcut, | 333 product_desc, ShellUtil::CURRENT_USER, alt_shortcut, |
| 324 create_all_shortcut); | 334 create_all_shortcut); |
| 325 ret = ret && ShellUtil::CreateChromeQuickLaunchShortcut(chrome_exe, | 335 ret = ret && ShellUtil::CreateChromeQuickLaunchShortcut(chrome_exe, |
| 326 ShellUtil::CURRENT_USER, create_all_shortcut); | 336 ShellUtil::CURRENT_USER, create_all_shortcut); |
| 327 } | 337 } |
| 328 | 338 |
| 329 return ret; | 339 return ret; |
| 330 } | 340 } |
| 331 | 341 |
| 332 // After a successful copying of all the files, this function is called to | 342 // After a successful copying of all the files, this function is called to |
| 333 // do a few post install tasks: | 343 // do a few post install tasks: |
| 334 // - Handle the case of in-use-update by updating "opv" key or deleting it if | 344 // - Handle the case of in-use-update by updating "opv" key or deleting it if |
| 335 // not required. | 345 // not required. |
| 336 // - Register any new dlls and unregister old dlls. | 346 // - Register any new dlls and unregister old dlls. |
| 347 // - If this is an MSI install, ensures that the MSI marker is set, and sets |
| 348 // it if not. |
| 337 // If these operations are successful, the function returns true, otherwise | 349 // If these operations are successful, the function returns true, otherwise |
| 338 // false. | 350 // false. |
| 339 bool DoPostInstallTasks(HKEY reg_root, | 351 bool DoPostInstallTasks(HKEY reg_root, |
| 340 const std::wstring& exe_path, | 352 const std::wstring& exe_path, |
| 341 const std::wstring& install_path, | 353 const std::wstring& install_path, |
| 342 const std::wstring& new_chrome_exe, | 354 const std::wstring& new_chrome_exe, |
| 343 const std::wstring& current_version, | 355 const std::wstring& current_version, |
| 344 const installer::Version& new_version) { | 356 const installer::Version& new_version) { |
| 345 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); | 357 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
| 346 std::wstring version_key = dist->GetVersionKey(); | 358 std::wstring version_key = dist->GetVersionKey(); |
| 347 | 359 |
| 360 bool is_system_install = (reg_root == HKEY_LOCAL_MACHINE); |
| 361 |
| 348 if (file_util::PathExists(FilePath::FromWStringHack(new_chrome_exe))) { | 362 if (file_util::PathExists(FilePath::FromWStringHack(new_chrome_exe))) { |
| 349 // Looks like this was in use update. So make sure we update the 'opv' key | 363 // Looks like this was in use update. So make sure we update the 'opv' key |
| 350 // with the current version that is active and 'cmd' key with the rename | 364 // with the current version that is active and 'cmd' key with the rename |
| 351 // command to run. | 365 // command to run. |
| 352 if (current_version.empty()) { | 366 if (current_version.empty()) { |
| 353 LOG(ERROR) << "New chrome.exe exists but current version is empty!"; | 367 LOG(ERROR) << "New chrome.exe exists but current version is empty!"; |
| 354 return false; | 368 return false; |
| 355 } | 369 } |
| 356 scoped_ptr<WorkItemList> inuse_list(WorkItem::CreateWorkItemList()); | 370 scoped_ptr<WorkItemList> inuse_list(WorkItem::CreateWorkItemList()); |
| 357 inuse_list->AddSetRegValueWorkItem(reg_root, | 371 inuse_list->AddSetRegValueWorkItem(reg_root, |
| 358 version_key, | 372 version_key, |
| 359 google_update::kRegOldVersionField, | 373 google_update::kRegOldVersionField, |
| 360 current_version.c_str(), | 374 current_version.c_str(), |
| 361 true); | 375 true); |
| 362 | 376 |
| 363 std::wstring rename_cmd(installer::GetInstallerPathUnderChrome( | 377 std::wstring rename_cmd(installer::GetInstallerPathUnderChrome( |
| 364 install_path, new_version.GetString())); | 378 install_path, new_version.GetString())); |
| 365 file_util::AppendToPath(&rename_cmd, | 379 file_util::AppendToPath(&rename_cmd, |
| 366 file_util::GetFilenameFromPath(exe_path)); | 380 file_util::GetFilenameFromPath(exe_path)); |
| 367 rename_cmd = L"\"" + rename_cmd + | 381 rename_cmd = L"\"" + rename_cmd + |
| 368 L"\" --" + installer_util::switches::kRenameChromeExe; | 382 L"\" --" + installer_util::switches::kRenameChromeExe; |
| 369 if (reg_root == HKEY_LOCAL_MACHINE) | 383 if (is_system_install) |
| 370 rename_cmd = rename_cmd + L" --" + installer_util::switches::kSystemLevel; | 384 rename_cmd = rename_cmd + L" --" + installer_util::switches::kSystemLevel; |
| 371 | 385 |
| 372 if (InstallUtil::IsChromeFrameProcess()) { | 386 if (InstallUtil::IsChromeFrameProcess()) { |
| 373 rename_cmd += L" --"; | 387 rename_cmd += L" --"; |
| 374 rename_cmd += installer_util::switches::kChromeFrame; | 388 rename_cmd += installer_util::switches::kChromeFrame; |
| 375 } | 389 } |
| 376 | 390 |
| 377 if (InstallUtil::IsChromeSxSProcess()) { | 391 if (InstallUtil::IsChromeSxSProcess()) { |
| 378 rename_cmd += L" --"; | 392 rename_cmd += L" --"; |
| 379 rename_cmd += installer_util::switches::kChromeSxS; | 393 rename_cmd += installer_util::switches::kChromeSxS; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 434 if (InstallUtil::BuildDLLRegistrationList(dll_path, kDllsToRegister, | 448 if (InstallUtil::BuildDLLRegistrationList(dll_path, kDllsToRegister, |
| 435 kNumDllsToRegister, true, | 449 kNumDllsToRegister, true, |
| 436 dll_list.get())) { | 450 dll_list.get())) { |
| 437 if (!dll_list->Do()) { | 451 if (!dll_list->Do()) { |
| 438 dll_list->Rollback(); | 452 dll_list->Rollback(); |
| 439 return false; | 453 return false; |
| 440 } | 454 } |
| 441 } | 455 } |
| 442 } | 456 } |
| 443 | 457 |
| 458 // If we're told that we're an MSI install, make sure to set the marker |
| 459 // in the client state key so that future updates do the right thing. |
| 460 if (InstallUtil::IsMSIProcess(is_system_install)) { |
| 461 if (!InstallUtil::SetMSIMarker(is_system_install, true)) |
| 462 return false; |
| 463 } |
| 464 |
| 444 return true; | 465 return true; |
| 445 } | 466 } |
| 446 | 467 |
| 447 // This method tells if we are running on 64 bit platform so that we can copy | 468 // This method tells if we are running on 64 bit platform so that we can copy |
| 448 // one extra exe. If the API call to determine 64 bit fails, we play it safe | 469 // one extra exe. If the API call to determine 64 bit fails, we play it safe |
| 449 // and return true anyway so that the executable can be copied. | 470 // and return true anyway so that the executable can be copied. |
| 450 bool Is64bit() { | 471 bool Is64bit() { |
| 451 typedef BOOL (WINAPI *WOW_FUNC)(HANDLE, PBOOL); | 472 typedef BOOL (WINAPI *WOW_FUNC)(HANDLE, PBOOL); |
| 452 BOOL is64 = FALSE; | 473 BOOL is64 = FALSE; |
| 453 | 474 |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 714 } | 735 } |
| 715 | 736 |
| 716 std::wstring latest_version_to_keep(new_version.GetString()); | 737 std::wstring latest_version_to_keep(new_version.GetString()); |
| 717 if (!current_version.empty()) | 738 if (!current_version.empty()) |
| 718 latest_version_to_keep.assign(current_version); | 739 latest_version_to_keep.assign(current_version); |
| 719 RemoveOldVersionDirs(install_path, latest_version_to_keep); | 740 RemoveOldVersionDirs(install_path, latest_version_to_keep); |
| 720 } | 741 } |
| 721 | 742 |
| 722 return result; | 743 return result; |
| 723 } | 744 } |
| OLD | NEW |