Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: chrome/installer/setup/uninstall.cc

Issue 2027063002: Introduce UserHiveVisitor for performing operations on local users' registry hives. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: gab review Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/installer/setup/BUILD.gn ('k') | chrome/installer/setup/user_hive_visitor.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « chrome/installer/setup/BUILD.gn ('k') | chrome/installer/setup/user_hive_visitor.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698