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 // This file defines the methods useful for uninstalling Chrome. | 5 // This file defines the methods useful for uninstalling Chrome. |
6 | 6 |
7 #include "chrome/installer/setup/uninstall.h" | 7 #include "chrome/installer/setup/uninstall.h" |
8 | 8 |
9 #include <windows.h> | 9 #include <windows.h> |
10 #include <stddef.h> | 10 #include <stddef.h> |
11 #include <stdint.h> | 11 #include <stdint.h> |
12 | 12 |
13 #include <vector> | 13 #include <vector> |
14 | 14 |
15 #include "base/base_paths.h" | 15 #include "base/base_paths.h" |
| 16 #include "base/bind.h" |
16 #include "base/files/file_enumerator.h" | 17 #include "base/files/file_enumerator.h" |
17 #include "base/files/file_util.h" | 18 #include "base/files/file_util.h" |
18 #include "base/macros.h" | 19 #include "base/macros.h" |
19 #include "base/path_service.h" | 20 #include "base/path_service.h" |
20 #include "base/process/kill.h" | 21 #include "base/process/kill.h" |
21 #include "base/strings/string16.h" | 22 #include "base/strings/string16.h" |
22 #include "base/strings/string_number_conversions.h" | 23 #include "base/strings/string_number_conversions.h" |
23 #include "base/strings/string_util.h" | 24 #include "base/strings/string_util.h" |
24 #include "base/strings/utf_string_conversions.h" | 25 #include "base/strings/utf_string_conversions.h" |
25 #include "base/win/registry.h" | 26 #include "base/win/registry.h" |
26 #include "base/win/scoped_handle.h" | 27 #include "base/win/scoped_handle.h" |
27 #include "base/win/shortcut.h" | 28 #include "base/win/shortcut.h" |
28 #include "base/win/windows_version.h" | 29 #include "base/win/windows_version.h" |
29 #include "chrome/common/chrome_constants.h" | 30 #include "chrome/common/chrome_constants.h" |
30 #include "chrome/common/chrome_paths.h" | 31 #include "chrome/common/chrome_paths.h" |
31 #include "chrome/common/chrome_result_codes.h" | 32 #include "chrome/common/chrome_result_codes.h" |
32 #include "chrome/installer/setup/app_launcher_installer.h" | 33 #include "chrome/installer/setup/app_launcher_installer.h" |
33 #include "chrome/installer/setup/install.h" | 34 #include "chrome/installer/setup/install.h" |
34 #include "chrome/installer/setup/install_worker.h" | 35 #include "chrome/installer/setup/install_worker.h" |
35 #include "chrome/installer/setup/setup_constants.h" | 36 #include "chrome/installer/setup/setup_constants.h" |
36 #include "chrome/installer/setup/setup_util.h" | 37 #include "chrome/installer/setup/setup_util.h" |
| 38 #include "chrome/installer/setup/user_hive_visitor.h" |
37 #include "chrome/installer/util/auto_launch_util.h" | 39 #include "chrome/installer/util/auto_launch_util.h" |
38 #include "chrome/installer/util/browser_distribution.h" | 40 #include "chrome/installer/util/browser_distribution.h" |
39 #include "chrome/installer/util/channel_info.h" | 41 #include "chrome/installer/util/channel_info.h" |
40 #include "chrome/installer/util/delete_after_reboot_helper.h" | 42 #include "chrome/installer/util/delete_after_reboot_helper.h" |
41 #include "chrome/installer/util/firewall_manager_win.h" | 43 #include "chrome/installer/util/firewall_manager_win.h" |
42 #include "chrome/installer/util/google_update_constants.h" | 44 #include "chrome/installer/util/google_update_constants.h" |
43 #include "chrome/installer/util/google_update_settings.h" | 45 #include "chrome/installer/util/google_update_settings.h" |
44 #include "chrome/installer/util/helper.h" | 46 #include "chrome/installer/util/helper.h" |
45 #include "chrome/installer/util/install_util.h" | 47 #include "chrome/installer/util/install_util.h" |
46 #include "chrome/installer/util/installation_state.h" | 48 #include "chrome/installer/util/installation_state.h" |
(...skipping 653 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
700 key.WriteValue(NULL, replacement_prog_id) != ERROR_SUCCESS)) { | 702 key.WriteValue(NULL, replacement_prog_id) != ERROR_SUCCESS)) { |
701 // The replacement ProgID is registered on the computer but the attempt | 703 // The replacement ProgID is registered on the computer but the attempt |
702 // to set it for the filetype failed. | 704 // to set it for the filetype failed. |
703 LOG(ERROR) << "Failed to restore system-level filetype association " | 705 LOG(ERROR) << "Failed to restore system-level filetype association " |
704 << assoc << " = " << replacement_prog_id; | 706 << assoc << " = " << replacement_prog_id; |
705 } | 707 } |
706 } | 708 } |
707 } | 709 } |
708 } | 710 } |
709 | 711 |
| 712 bool DeleteUserRegistryKeys(const std::vector<const base::string16*>* key_paths, |
| 713 const wchar_t* user_sid, |
| 714 base::win::RegKey* key) { |
| 715 for (const auto& key_path : *key_paths) { |
| 716 LONG result = key->DeleteKey(key_path->c_str()); |
| 717 if (result == ERROR_SUCCESS) { |
| 718 VLOG(1) << "Deleted " << user_sid << "\\" << *key_path; |
| 719 } else if (result != ERROR_FILE_NOT_FOUND) { |
| 720 ::SetLastError(result); |
| 721 PLOG(ERROR) << "Failed deleting " << user_sid << "\\" << *key_path; |
| 722 } |
| 723 } |
| 724 return true; |
| 725 } |
| 726 |
710 // Removes Active Setup entries from the registry. This cannot be done through | 727 // Removes Active Setup entries from the registry. This cannot be done through |
711 // a work items list as usual because of different paths based on conditionals, | 728 // a work items list as usual because of different paths based on conditionals, |
712 // but otherwise respects the no rollback/best effort uninstall mentality. | 729 // but otherwise respects the no rollback/best effort uninstall mentality. |
713 // This will only apply for system-level installs of Chrome/Chromium and will be | 730 // This will only apply for system-level installs of Chrome/Chromium and will be |
714 // a no-op for all other types of installs. | 731 // a no-op for all other types of installs. |
715 void UninstallActiveSetupEntries(const InstallerState& installer_state, | 732 void UninstallActiveSetupEntries(const InstallerState& installer_state, |
716 const Product& product) { | 733 const Product& product) { |
717 VLOG(1) << "Uninstalling registry entries for Active Setup."; | 734 VLOG(1) << "Uninstalling registry entries for Active Setup."; |
718 BrowserDistribution* distribution = product.distribution(); | 735 BrowserDistribution* distribution = product.distribution(); |
719 | 736 |
(...skipping 20 matching lines...) Expand all Loading... |
740 // Setup again as desired. | 757 // Setup again as desired. |
741 // | 758 // |
742 // It is however very hard to delete those values as the registry hives for | 759 // It is however very hard to delete those values as the registry hives for |
743 // other users are not loaded by default under HKEY_USERS (unless a user is | 760 // other users are not loaded by default under HKEY_USERS (unless a user is |
744 // logged on or has a process impersonating him). | 761 // logged on or has a process impersonating him). |
745 // | 762 // |
746 // Following our best effort uninstall practices, try to delete the value in | 763 // Following our best effort uninstall practices, try to delete the value in |
747 // all users hives. If a given user's hive is not loaded, try to load it to | 764 // all users hives. If a given user's hive is not loaded, try to load it to |
748 // proceed with the deletion (failure to do so is ignored). | 765 // proceed with the deletion (failure to do so is ignored). |
749 | 766 |
750 VLOG(1) << "Uninstall per-user Active Setup keys."; | |
751 | |
752 static const wchar_t kProfileList[] = | |
753 L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\"; | |
754 | |
755 // Windows automatically adds Wow6432Node when creating/deleting the HKLM key, | 767 // Windows automatically adds Wow6432Node when creating/deleting the HKLM key, |
756 // but doesn't seem to do so when manually deleting the user-level keys it | 768 // but doesn't seem to do so when manually deleting the user-level keys it |
757 // created. | 769 // created. |
758 base::string16 alternate_active_setup_path(active_setup_path); | 770 base::string16 alternate_active_setup_path(active_setup_path); |
759 alternate_active_setup_path.insert(arraysize("Software\\") - 1, | 771 alternate_active_setup_path.insert(arraysize("Software\\") - 1, |
760 L"Wow6432Node\\"); | 772 L"Wow6432Node\\"); |
761 | 773 |
762 // These two privileges are required by RegLoadKey() and RegUnloadKey() below. | 774 VLOG(1) << "Uninstall per-user Active Setup keys."; |
763 ScopedTokenPrivilege se_restore_name_privilege(SE_RESTORE_NAME); | 775 std::vector<const base::string16*> paths = {&active_setup_path, |
764 ScopedTokenPrivilege se_backup_name_privilege(SE_BACKUP_NAME); | 776 &alternate_active_setup_path}; |
765 if (!se_restore_name_privilege.is_enabled() || | 777 VisitUserHives(base::Bind(&DeleteUserRegistryKeys, base::Unretained(&paths))); |
766 !se_backup_name_privilege.is_enabled()) { | |
767 // This is not a critical failure as those privileges aren't required to | |
768 // clean hives that are already loaded, but attempts to LoadRegKey() below | |
769 // will fail. | |
770 LOG(WARNING) << "Failed to enable privileges required to load registry " | |
771 "hives."; | |
772 } | |
773 | |
774 for (base::win::RegistryKeyIterator it(HKEY_LOCAL_MACHINE, kProfileList); | |
775 it.Valid(); ++it) { | |
776 const wchar_t* profile_sid = it.Name(); | |
777 | |
778 VLOG(1) << "Uninstalling Active Setup key for " << profile_sid; | |
779 | |
780 // First check if this user's registry hive needs to be loaded in | |
781 // HKEY_USERS. | |
782 base::win::RegKey user_reg_root_probe( | |
783 HKEY_USERS, profile_sid, KEY_READ); | |
784 bool loaded_hive = false; | |
785 if (user_reg_root_probe.Valid()) { | |
786 VLOG(1) << "Registry hive already loaded for " << profile_sid; | |
787 } else { | |
788 VLOG(1) << "Attempting to load registry hive for " << profile_sid; | |
789 | |
790 base::string16 reg_profile_info_path(kProfileList); | |
791 reg_profile_info_path.append(profile_sid); | |
792 base::win::RegKey reg_profile_info_key( | |
793 HKEY_LOCAL_MACHINE, reg_profile_info_path.c_str(), KEY_READ); | |
794 | |
795 base::string16 profile_path; | |
796 LONG result = reg_profile_info_key.ReadValue(L"ProfileImagePath", | |
797 &profile_path); | |
798 if (result != ERROR_SUCCESS) { | |
799 LOG(ERROR) << "Error reading ProfileImagePath: " << result; | |
800 continue; | |
801 } | |
802 base::FilePath registry_hive_file(profile_path); | |
803 registry_hive_file = registry_hive_file.AppendASCII("NTUSER.DAT"); | |
804 | |
805 result = RegLoadKey(HKEY_USERS, profile_sid, | |
806 registry_hive_file.value().c_str()); | |
807 if (result != ERROR_SUCCESS) { | |
808 LOG(ERROR) << "Error loading registry hive: " << result; | |
809 continue; | |
810 } | |
811 | |
812 VLOG(1) << "Loaded registry hive for " << profile_sid; | |
813 loaded_hive = true; | |
814 } | |
815 | |
816 base::win::RegKey user_reg_root( | |
817 HKEY_USERS, profile_sid, KEY_ALL_ACCESS); | |
818 | |
819 LONG result = user_reg_root.DeleteKey(active_setup_path.c_str()); | |
820 if (result != ERROR_SUCCESS) { | |
821 result = user_reg_root.DeleteKey(alternate_active_setup_path.c_str()); | |
822 if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) { | |
823 LOG(ERROR) << "Failed to delete key at " << active_setup_path | |
824 << " and at " << alternate_active_setup_path | |
825 << ", result: " << result; | |
826 } | |
827 } | |
828 VLOG_IF(1, result == ERROR_SUCCESS) | |
829 << "Deleted Active Setup entry for " << profile_sid; | |
830 VLOG_IF(1, result == ERROR_FILE_NOT_FOUND) | |
831 << "No Active Setup entry to delete for " << profile_sid; | |
832 | |
833 if (loaded_hive) { | |
834 user_reg_root.Close(); | |
835 if (RegUnLoadKey(HKEY_USERS, profile_sid) == ERROR_SUCCESS) | |
836 VLOG(1) << "Unloaded registry hive for " << profile_sid; | |
837 else | |
838 LOG(ERROR) << "Error unloading registry hive for " << profile_sid; | |
839 } | |
840 } | |
841 } | 778 } |
842 | 779 |
843 // Removes the persistent blacklist state for the current user. Note: this will | 780 // Removes the persistent blacklist state for the current user. Note: this will |
844 // not remove the state for users other than the one uninstalling Chrome on a | 781 // not remove the state for users other than the one uninstalling Chrome on a |
845 // system-level install (http://crbug.com/388725). Doing so would require | 782 // system-level install (http://crbug.com/388725). Doing so would require |
846 // extracting the per-user registry hive iteration from | 783 // extracting the per-user registry hive iteration from |
847 // UninstallActiveSetupEntries so that it could service multiple tasks. | 784 // UninstallActiveSetupEntries so that it could service multiple tasks. |
848 void RemoveBlacklistState() { | 785 void RemoveBlacklistState() { |
849 InstallUtil::DeleteRegistryKey(HKEY_CURRENT_USER, | 786 InstallUtil::DeleteRegistryKey(HKEY_CURRENT_USER, |
850 blacklist::kRegistryBeaconPath, | 787 blacklist::kRegistryBeaconPath, |
(...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1436 // If we need a reboot to continue, schedule the parent directories for | 1373 // If we need a reboot to continue, schedule the parent directories for |
1437 // deletion unconditionally. If they are not empty, the session manager | 1374 // deletion unconditionally. If they are not empty, the session manager |
1438 // will not delete them on reboot. | 1375 // will not delete them on reboot. |
1439 ScheduleParentAndGrandparentForDeletion(target_path); | 1376 ScheduleParentAndGrandparentForDeletion(target_path); |
1440 } else if (DeleteChromeDirectoriesIfEmpty(target_path) == DELETE_FAILED) { | 1377 } else if (DeleteChromeDirectoriesIfEmpty(target_path) == DELETE_FAILED) { |
1441 *uninstall_status = UNINSTALL_FAILED; | 1378 *uninstall_status = UNINSTALL_FAILED; |
1442 } | 1379 } |
1443 } | 1380 } |
1444 | 1381 |
1445 } // namespace installer | 1382 } // namespace installer |
OLD | NEW |