Chromium Code Reviews| Index: chrome/installer/setup/uninstall.cc |
| diff --git a/chrome/installer/setup/uninstall.cc b/chrome/installer/setup/uninstall.cc |
| index d1b67ffbc83fffd74410a75255d97e338d86a55c..6b7e4de5d1fd72c836777ea7e2389fbc53c5f6ef 100644 |
| --- a/chrome/installer/setup/uninstall.cc |
| +++ b/chrome/installer/setup/uninstall.cc |
| @@ -50,8 +50,8 @@ |
| #include "rlz/lib/rlz_lib.h" |
| using base::win::RegKey; |
| -using installer::InstallStatus; |
| -using installer::MasterPreferences; |
| + |
| +namespace installer { |
| namespace { |
| @@ -64,7 +64,7 @@ void DeleteInstallTempDir(const base::FilePath& target_path) { |
| base::FilePath temp_path(target_path.DirName().Append( |
| installer::kInstallTempDir)); |
| if (base::DirectoryExists(temp_path)) { |
| - installer::SelfCleaningTempDir temp_dir; |
| + SelfCleaningTempDir temp_dir; |
| if (!temp_dir.Initialize(target_path.DirName(), |
| installer::kInstallTempDir) || |
| !temp_dir.Delete()) { |
| @@ -77,16 +77,16 @@ void DeleteInstallTempDir(const base::FilePath& target_path) { |
| // adds to |update_list| the work item to update the corresponding "ap" |
| // registry value specified in |channel_info|. |
| void AddChannelValueUpdateWorkItems( |
| - const installer::InstallationState& original_state, |
| - const installer::InstallerState& installer_state, |
| - const installer::ChannelInfo& channel_info, |
| + const InstallationState& original_state, |
| + const InstallerState& installer_state, |
| + const ChannelInfo& channel_info, |
| const std::vector<BrowserDistribution::Type>& dist_types, |
| WorkItemList* update_list) { |
| const bool system_level = installer_state.system_install(); |
| const HKEY reg_root = installer_state.root_key(); |
| for (size_t i = 0; i < dist_types.size(); ++i) { |
| BrowserDistribution::Type dist_type = dist_types[i]; |
| - const installer::ProductState* product_state = |
| + const ProductState* product_state = |
| original_state.GetProductState(system_level, dist_type); |
| // Only modify other products if they're installed and multi. |
| if (product_state != NULL && |
| @@ -112,17 +112,16 @@ void AddChannelValueUpdateWorkItems( |
| // Specifically, removes the flags associated with this product ("-chrome" or |
| // "-chromeframe") from the "ap" values for all other installed products and for |
| // the multi-installer package. |
| -void ProcessGoogleUpdateItems( |
| - const installer::InstallationState& original_state, |
| - const installer::InstallerState& installer_state, |
| - const installer::Product& product) { |
| +void ProcessGoogleUpdateItems(const InstallationState& original_state, |
| + const InstallerState& installer_state, |
| + const Product& product) { |
| DCHECK(installer_state.is_multi_install()); |
| const bool system_level = installer_state.system_install(); |
| BrowserDistribution* distribution = product.distribution(); |
| - const installer::ProductState* product_state = |
| + const ProductState* product_state = |
| original_state.GetProductState(system_level, distribution->GetType()); |
| DCHECK(product_state != NULL); |
| - installer::ChannelInfo channel_info; |
| + ChannelInfo channel_info; |
| // Remove product's flags from the channel value. |
| channel_info.set_value(product_state->channel().value()); |
| @@ -147,9 +146,8 @@ void ProcessGoogleUpdateItems( |
| } |
| } |
| -void ProcessOnOsUpgradeWorkItems( |
| - const installer::InstallerState& installer_state, |
| - const installer::Product& product) { |
| +void ProcessOnOsUpgradeWorkItems(const InstallerState& installer_state, |
| + const Product& product) { |
| scoped_ptr<WorkItemList> work_item_list( |
| WorkItem::CreateNoRollbackWorkItemList()); |
| AddOsUpgradeWorkItems(installer_state, base::FilePath(), Version(), product, |
| @@ -158,12 +156,11 @@ void ProcessOnOsUpgradeWorkItems( |
| LOG(ERROR) << "Failed to remove on-os-upgrade command."; |
| } |
| -void ProcessIELowRightsPolicyWorkItems( |
| - const installer::InstallerState& installer_state) { |
| +void ProcessIELowRightsPolicyWorkItems(const InstallerState& installer_state) { |
| scoped_ptr<WorkItemList> work_items(WorkItem::CreateNoRollbackWorkItemList()); |
| AddDeleteOldIELowRightsPolicyWorkItems(installer_state, work_items.get()); |
| work_items->Do(); |
| - installer::RefreshElevationPolicy(); |
| + RefreshElevationPolicy(); |
| } |
| void ClearRlzProductState() { |
| @@ -187,11 +184,10 @@ void ClearRlzProductState() { |
| // * non-multi product being uninstalled: remove both |
| // * any multi product left besides App Host: keep both |
| // * only App Host left: keep setup.exe |
| -void CheckShouldRemoveSetupAndArchive( |
| - const installer::InstallationState& original_state, |
| - const installer::InstallerState& installer_state, |
| - bool* remove_setup, |
| - bool* remove_archive) { |
| +void CheckShouldRemoveSetupAndArchive(const InstallationState& original_state, |
| + const InstallerState& installer_state, |
| + bool* remove_setup, |
| + bool* remove_archive) { |
| *remove_setup = true; |
| *remove_archive = true; |
| @@ -204,9 +200,8 @@ void CheckShouldRemoveSetupAndArchive( |
| for (size_t i = 0; i < BrowserDistribution::NUM_TYPES; ++i) { |
| BrowserDistribution::Type dist_type = |
| static_cast<BrowserDistribution::Type>(i); |
| - const installer::ProductState* product_state = |
| - original_state.GetProductState( |
| - installer_state.system_install(), dist_type); |
| + const ProductState* product_state = original_state.GetProductState( |
| + installer_state.system_install(), dist_type); |
| // If the product is installed, in multi mode, and is not part of the |
| // active uninstallation... |
| if (product_state && product_state->is_multi_install() && |
| @@ -260,10 +255,6 @@ bool RemoveInstallerFiles(const base::FilePath& installer_directory, |
| return success; |
| } |
| -} // namespace |
| - |
| -namespace installer { |
| - |
| // Kills all Chrome processes, immediately. |
| void CloseAllChromeProcesses() { |
| base::CleanupProcesses(installer::kChromeExe, base::TimeDelta(), |
| @@ -395,62 +386,51 @@ DeleteResult DeleteEmptyDir(const base::FilePath& path) { |
| return DELETE_FAILED; |
| } |
| -void GetLocalStateFolders(const Product& product, |
| - std::vector<base::FilePath>* paths) { |
| +base::FilePath GetUserDataDir(const Product& product) { |
| // Obtain the location of the user profile data. |
| - product.GetUserDataPaths(paths); |
| - LOG_IF(ERROR, paths->empty()) |
| + base::FilePath user_data_dir = product.GetUserDataPath(); |
| + LOG_IF(ERROR, user_data_dir.empty()) |
| << "Could not retrieve user's profile directory."; |
| + |
| + return user_data_dir; |
| } |
| // Creates a copy of the local state file and returns a path to the copy. |
| -base::FilePath BackupLocalStateFile( |
| - const std::vector<base::FilePath>& local_state_folders) { |
| +base::FilePath BackupLocalStateFile(const base::FilePath& user_data_dir) { |
| base::FilePath backup; |
| - |
| - // Copy the first local state file that is found. |
| - for (size_t i = 0; i < local_state_folders.size(); ++i) { |
| - const base::FilePath& local_state_folder = local_state_folders[i]; |
| - base::FilePath state_file( |
| - local_state_folder.Append(chrome::kLocalStateFilename)); |
| - if (!base::PathExists(state_file)) |
| - continue; |
| - if (!base::CreateTemporaryFile(&backup)) |
| - LOG(ERROR) << "Failed to create temporary file for Local State."; |
| - else |
| - base::CopyFile(state_file, backup); |
| - break; |
| - } |
| + base::FilePath state_file( |
| + user_data_dir.Append(chrome::kLocalStateFilename)); |
| + if (!base::CreateTemporaryFile(&backup)) |
| + LOG(ERROR) << "Failed to create temporary file for Local State."; |
| + else |
| + base::CopyFile(state_file, backup); |
| return backup; |
| } |
| -// Deletes all user data directories for a product. |
| -DeleteResult DeleteLocalState( |
| - const std::vector<base::FilePath>& local_state_folders, |
| - bool schedule_on_failure) { |
| - if (local_state_folders.empty()) |
| +// Deletes a given user data directory as well as the containing product |
| +// directories if they are empty (e.g., "Google\Chrome"). |
| +DeleteResult DeleteUserDataDir(const base::FilePath& user_data_dir, |
| + bool schedule_on_failure) { |
| + if (user_data_dir.empty()) |
| return DELETE_SUCCEEDED; |
| DeleteResult result = DELETE_SUCCEEDED; |
| - for (size_t i = 0; i < local_state_folders.size(); ++i) { |
| - const base::FilePath& user_local_state = local_state_folders[i]; |
| - VLOG(1) << "Deleting user profile " << user_local_state.value(); |
| - if (!base::DeleteFile(user_local_state, true)) { |
| - LOG(ERROR) << "Failed to delete user profile dir: " |
| - << user_local_state.value(); |
| - if (schedule_on_failure) { |
| - ScheduleDirectoryForDeletion(user_local_state); |
| - result = DELETE_REQUIRES_REBOOT; |
| - } else { |
| - result = DELETE_FAILED; |
| - } |
| + VLOG(1) << "Deleting user profile " << user_data_dir.value(); |
| + if (!base::DeleteFile(user_data_dir, true)) { |
| + LOG(ERROR) << "Failed to delete user profile dir: " |
| + << user_data_dir.value(); |
| + if (schedule_on_failure) { |
| + ScheduleDirectoryForDeletion(user_data_dir); |
| + result = DELETE_REQUIRES_REBOOT; |
| + } else { |
| + result = DELETE_FAILED; |
| } |
| } |
| if (result == DELETE_REQUIRES_REBOOT) { |
| - ScheduleParentAndGrandparentForDeletion(local_state_folders[0]); |
| + ScheduleParentAndGrandparentForDeletion(user_data_dir); |
| } else { |
| - const base::FilePath user_data_dir(local_state_folders[0].DirName()); |
| + const base::FilePath user_data_dir(user_data_dir.DirName()); |
|
Nico
2014/07/21 14:47:44
clang remarks:
..\..\chrome\installer\setup\unins
|
| if (!user_data_dir.empty() && |
| DeleteEmptyDir(user_data_dir) == DELETE_SUCCEEDED) { |
| const base::FilePath product_dir(user_data_dir.DirName()); |
| @@ -522,27 +502,6 @@ bool MoveSetupOutOfInstallFolder(const InstallerState& installer_state, |
| return true; |
| } |
| -DeleteResult DeleteChromeDirectoriesIfEmpty( |
| - const base::FilePath& application_directory) { |
| - DeleteResult result(DeleteEmptyDir(application_directory)); |
| - if (result == DELETE_SUCCEEDED) { |
| - // Now check and delete if the parent directories are empty |
| - // For example Google\Chrome or Chromium |
| - const base::FilePath product_directory(application_directory.DirName()); |
| - if (!product_directory.empty()) { |
| - result = DeleteEmptyDir(product_directory); |
| - if (result == DELETE_SUCCEEDED) { |
| - const base::FilePath vendor_directory(product_directory.DirName()); |
| - if (!vendor_directory.empty()) |
| - result = DeleteEmptyDir(vendor_directory); |
| - } |
| - } |
| - } |
| - if (result == DELETE_NOT_EMPTY) |
| - result = DELETE_SUCCEEDED; |
| - return result; |
| -} |
| - |
| DeleteResult DeleteAppHostFilesAndFolders(const InstallerState& installer_state, |
| const Version& installed_version) { |
| const base::FilePath& target_path = installer_state.target_path(); |
| @@ -758,6 +717,164 @@ void RemoveFiletypeRegistration(const InstallerState& installer_state, |
| } |
| } |
| +// Builds and executes a work item list to remove DelegateExecute verb handler |
| +// work items for |product|. This will be a noop for products whose |
| +// corresponding BrowserDistribution implementations do not publish a CLSID via |
| +// GetCommandExecuteImplClsid. |
| +bool ProcessDelegateExecuteWorkItems(const InstallerState& installer_state, |
| + const Product& product) { |
| + scoped_ptr<WorkItemList> item_list(WorkItem::CreateNoRollbackWorkItemList()); |
| + AddDelegateExecuteWorkItems(installer_state, base::FilePath(), Version(), |
| + product, item_list.get()); |
| + return item_list->Do(); |
| +} |
| + |
| +// Removes Active Setup entries from the registry. This cannot be done through |
| +// a work items list as usual because of different paths based on conditionals, |
| +// but otherwise respects the no rollback/best effort uninstall mentality. |
| +// This will only apply for system-level installs of Chrome/Chromium and will be |
| +// a no-op for all other types of installs. |
| +void UninstallActiveSetupEntries(const InstallerState& installer_state, |
| + const Product& product) { |
| + VLOG(1) << "Uninstalling registry entries for ActiveSetup."; |
| + BrowserDistribution* distribution = product.distribution(); |
| + |
| + if (!product.is_chrome() || !installer_state.system_install()) { |
| + const char* install_level = |
| + installer_state.system_install() ? "system" : "user"; |
| + VLOG(1) << "No Active Setup processing to do for " << install_level |
| + << "-level " << distribution->GetDisplayName(); |
| + return; |
| + } |
| + |
| + const base::string16 active_setup_path( |
| + InstallUtil::GetActiveSetupPath(distribution)); |
| + InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, active_setup_path); |
| + |
| + // Windows leaves keys behind in HKCU\\Software\\(Wow6432Node\\)?Microsoft\\ |
| + // Active Setup\\Installed Components\\{guid} |
| + // for every user that logged in since system-level Chrome was installed. |
| + // This is a problem because Windows compares the value of the Version subkey |
| + // in there with the value of the Version subkey in the matching HKLM entries |
| + // before running Chrome's Active Setup so if Chrome was to be reinstalled |
| + // with a lesser version (e.g. switching back to a more stable channel), the |
| + // affected users would not have Chrome's Active Setup called until Chrome |
| + // eventually updated passed that user's registered Version. |
| + // |
| + // It is however very hard to delete those values as the registry hives for |
| + // other users are not loaded by default under HKEY_USERS (unless a user is |
| + // logged on or has a process impersonating him). |
| + // |
| + // Following our best effort uninstall practices, try to delete the value in |
| + // all users hives. If a given user's hive is not loaded, try to load it to |
| + // proceed with the deletion (failure to do so is ignored). |
| + |
| + static const wchar_t kProfileList[] = |
| + L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\"; |
| + |
| + // Windows automatically adds Wow6432Node when creating/deleting the HKLM key, |
| + // but doesn't seem to do so when manually deleting the user-level keys it |
| + // created. |
| + base::string16 alternate_active_setup_path(active_setup_path); |
| + alternate_active_setup_path.insert(arraysize("Software\\") - 1, |
| + L"Wow6432Node\\"); |
| + |
| + // These two privileges are required by RegLoadKey() and RegUnloadKey() below. |
| + ScopedTokenPrivilege se_restore_name_privilege(SE_RESTORE_NAME); |
| + ScopedTokenPrivilege se_backup_name_privilege(SE_BACKUP_NAME); |
| + if (!se_restore_name_privilege.is_enabled() || |
| + !se_backup_name_privilege.is_enabled()) { |
| + // This is not a critical failure as those privileges aren't required to |
| + // clean hives that are already loaded, but attempts to LoadRegKey() below |
| + // will fail. |
| + LOG(WARNING) << "Failed to enable privileges required to load registry " |
| + "hives."; |
| + } |
| + |
| + for (base::win::RegistryKeyIterator it(HKEY_LOCAL_MACHINE, kProfileList); |
| + it.Valid(); ++it) { |
| + const wchar_t* profile_sid = it.Name(); |
| + |
| + // First check if this user's registry hive needs to be loaded in |
| + // HKEY_USERS. |
| + base::win::RegKey user_reg_root_probe( |
| + HKEY_USERS, profile_sid, KEY_READ); |
| + bool loaded_hive = false; |
| + if (!user_reg_root_probe.Valid()) { |
| + VLOG(1) << "Attempting to load registry hive for " << profile_sid; |
| + |
| + base::string16 reg_profile_info_path(kProfileList); |
| + reg_profile_info_path.append(profile_sid); |
| + base::win::RegKey reg_profile_info_key( |
| + HKEY_LOCAL_MACHINE, reg_profile_info_path.c_str(), KEY_READ); |
| + |
| + base::string16 profile_path; |
| + LONG result = reg_profile_info_key.ReadValue(L"ProfileImagePath", |
| + &profile_path); |
| + if (result != ERROR_SUCCESS) { |
| + LOG(ERROR) << "Error reading ProfileImagePath: " << result; |
| + continue; |
| + } |
| + base::FilePath registry_hive_file(profile_path); |
| + registry_hive_file = registry_hive_file.AppendASCII("NTUSER.DAT"); |
| + |
| + result = RegLoadKey(HKEY_USERS, profile_sid, |
| + registry_hive_file.value().c_str()); |
| + if (result != ERROR_SUCCESS) { |
| + LOG(ERROR) << "Error loading registry hive: " << result; |
| + continue; |
| + } |
| + |
| + VLOG(1) << "Loaded registry hive for " << profile_sid; |
| + loaded_hive = true; |
| + } |
| + |
| + base::win::RegKey user_reg_root( |
| + HKEY_USERS, profile_sid, KEY_ALL_ACCESS); |
| + |
| + LONG result = user_reg_root.DeleteKey(active_setup_path.c_str()); |
| + if (result != ERROR_SUCCESS) { |
| + result = user_reg_root.DeleteKey(alternate_active_setup_path.c_str()); |
| + if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) { |
| + LOG(ERROR) << "Failed to delete key at " << active_setup_path |
| + << " and at " << alternate_active_setup_path |
| + << ", result: " << result; |
| + } |
| + } |
| + |
| + if (loaded_hive) { |
| + user_reg_root.Close(); |
| + if (RegUnLoadKey(HKEY_USERS, profile_sid) == ERROR_SUCCESS) |
| + VLOG(1) << "Unloaded registry hive for " << profile_sid; |
| + else |
| + LOG(ERROR) << "Error unloading registry hive for " << profile_sid; |
| + } |
| + } |
| +} |
| + |
| +} // namespace |
| + |
| +DeleteResult DeleteChromeDirectoriesIfEmpty( |
| + const base::FilePath& application_directory) { |
| + DeleteResult result(DeleteEmptyDir(application_directory)); |
| + if (result == DELETE_SUCCEEDED) { |
| + // Now check and delete if the parent directories are empty |
| + // For example Google\Chrome or Chromium |
| + const base::FilePath product_directory(application_directory.DirName()); |
| + if (!product_directory.empty()) { |
| + result = DeleteEmptyDir(product_directory); |
| + if (result == DELETE_SUCCEEDED) { |
| + const base::FilePath vendor_directory(product_directory.DirName()); |
| + if (!vendor_directory.empty()) |
| + result = DeleteEmptyDir(vendor_directory); |
| + } |
| + } |
| + } |
| + if (result == DELETE_NOT_EMPTY) |
| + result = DELETE_SUCCEEDED; |
| + return result; |
| +} |
| + |
| bool DeleteChromeRegistrationKeys(const InstallerState& installer_state, |
| BrowserDistribution* dist, |
| HKEY root, |
| @@ -929,141 +1046,6 @@ const wchar_t kChromeExtProgId[] = L"ChromiumExt"; |
| } |
| } |
| -// Builds and executes a work item list to remove DelegateExecute verb handler |
| -// work items for |product|. This will be a noop for products whose |
| -// corresponding BrowserDistribution implementations do not publish a CLSID via |
| -// GetCommandExecuteImplClsid. |
| -bool ProcessDelegateExecuteWorkItems(const InstallerState& installer_state, |
| - const Product& product) { |
| - scoped_ptr<WorkItemList> item_list(WorkItem::CreateNoRollbackWorkItemList()); |
| - AddDelegateExecuteWorkItems(installer_state, base::FilePath(), Version(), |
| - product, item_list.get()); |
| - return item_list->Do(); |
| -} |
| - |
| -// Removes Active Setup entries from the registry. This cannot be done through |
| -// a work items list as usual because of different paths based on conditionals, |
| -// but otherwise respects the no rollback/best effort uninstall mentality. |
| -// This will only apply for system-level installs of Chrome/Chromium and will be |
| -// a no-op for all other types of installs. |
| -void UninstallActiveSetupEntries(const InstallerState& installer_state, |
| - const Product& product) { |
| - VLOG(1) << "Uninstalling registry entries for ActiveSetup."; |
| - BrowserDistribution* distribution = product.distribution(); |
| - |
| - if (!product.is_chrome() || !installer_state.system_install()) { |
| - const char* install_level = |
| - installer_state.system_install() ? "system" : "user"; |
| - VLOG(1) << "No Active Setup processing to do for " << install_level |
| - << "-level " << distribution->GetDisplayName(); |
| - return; |
| - } |
| - |
| - const base::string16 active_setup_path( |
| - InstallUtil::GetActiveSetupPath(distribution)); |
| - InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, active_setup_path); |
| - |
| - // Windows leaves keys behind in HKCU\\Software\\(Wow6432Node\\)?Microsoft\\ |
| - // Active Setup\\Installed Components\\{guid} |
| - // for every user that logged in since system-level Chrome was installed. |
| - // This is a problem because Windows compares the value of the Version subkey |
| - // in there with the value of the Version subkey in the matching HKLM entries |
| - // before running Chrome's Active Setup so if Chrome was to be reinstalled |
| - // with a lesser version (e.g. switching back to a more stable channel), the |
| - // affected users would not have Chrome's Active Setup called until Chrome |
| - // eventually updated passed that user's registered Version. |
| - // |
| - // It is however very hard to delete those values as the registry hives for |
| - // other users are not loaded by default under HKEY_USERS (unless a user is |
| - // logged on or has a process impersonating him). |
| - // |
| - // Following our best effort uninstall practices, try to delete the value in |
| - // all users hives. If a given user's hive is not loaded, try to load it to |
| - // proceed with the deletion (failure to do so is ignored). |
| - |
| - static const wchar_t kProfileList[] = |
| - L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\"; |
| - |
| - // Windows automatically adds Wow6432Node when creating/deleting the HKLM key, |
| - // but doesn't seem to do so when manually deleting the user-level keys it |
| - // created. |
| - base::string16 alternate_active_setup_path(active_setup_path); |
| - alternate_active_setup_path.insert(arraysize("Software\\") - 1, |
| - L"Wow6432Node\\"); |
| - |
| - // These two privileges are required by RegLoadKey() and RegUnloadKey() below. |
| - ScopedTokenPrivilege se_restore_name_privilege(SE_RESTORE_NAME); |
| - ScopedTokenPrivilege se_backup_name_privilege(SE_BACKUP_NAME); |
| - if (!se_restore_name_privilege.is_enabled() || |
| - !se_backup_name_privilege.is_enabled()) { |
| - // This is not a critical failure as those privileges aren't required to |
| - // clean hives that are already loaded, but attempts to LoadRegKey() below |
| - // will fail. |
| - LOG(WARNING) << "Failed to enable privileges required to load registry " |
| - "hives."; |
| - } |
| - |
| - for (base::win::RegistryKeyIterator it(HKEY_LOCAL_MACHINE, kProfileList); |
| - it.Valid(); ++it) { |
| - const wchar_t* profile_sid = it.Name(); |
| - |
| - // First check if this user's registry hive needs to be loaded in |
| - // HKEY_USERS. |
| - base::win::RegKey user_reg_root_probe( |
| - HKEY_USERS, profile_sid, KEY_READ); |
| - bool loaded_hive = false; |
| - if (!user_reg_root_probe.Valid()) { |
| - VLOG(1) << "Attempting to load registry hive for " << profile_sid; |
| - |
| - base::string16 reg_profile_info_path(kProfileList); |
| - reg_profile_info_path.append(profile_sid); |
| - base::win::RegKey reg_profile_info_key( |
| - HKEY_LOCAL_MACHINE, reg_profile_info_path.c_str(), KEY_READ); |
| - |
| - base::string16 profile_path; |
| - LONG result = reg_profile_info_key.ReadValue(L"ProfileImagePath", |
| - &profile_path); |
| - if (result != ERROR_SUCCESS) { |
| - LOG(ERROR) << "Error reading ProfileImagePath: " << result; |
| - continue; |
| - } |
| - base::FilePath registry_hive_file(profile_path); |
| - registry_hive_file = registry_hive_file.AppendASCII("NTUSER.DAT"); |
| - |
| - result = RegLoadKey(HKEY_USERS, profile_sid, |
| - registry_hive_file.value().c_str()); |
| - if (result != ERROR_SUCCESS) { |
| - LOG(ERROR) << "Error loading registry hive: " << result; |
| - continue; |
| - } |
| - |
| - VLOG(1) << "Loaded registry hive for " << profile_sid; |
| - loaded_hive = true; |
| - } |
| - |
| - base::win::RegKey user_reg_root( |
| - HKEY_USERS, profile_sid, KEY_ALL_ACCESS); |
| - |
| - LONG result = user_reg_root.DeleteKey(active_setup_path.c_str()); |
| - if (result != ERROR_SUCCESS) { |
| - result = user_reg_root.DeleteKey(alternate_active_setup_path.c_str()); |
| - if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) { |
| - LOG(ERROR) << "Failed to delete key at " << active_setup_path |
| - << " and at " << alternate_active_setup_path |
| - << ", result: " << result; |
| - } |
| - } |
| - |
| - if (loaded_hive) { |
| - user_reg_root.Close(); |
| - if (RegUnLoadKey(HKEY_USERS, profile_sid) == ERROR_SUCCESS) |
| - VLOG(1) << "Unloaded registry hive for " << profile_sid; |
| - else |
| - LOG(ERROR) << "Error unloading registry hive for " << profile_sid; |
| - } |
| - } |
| -} |
| - |
| InstallStatus UninstallProduct(const InstallationState& original_state, |
| const InstallerState& installer_state, |
| const base::FilePath& setup_exe, |
| @@ -1332,9 +1314,8 @@ InstallStatus UninstallProduct(const InstallationState& original_state, |
| // When deleting files, we must make sure that we're either a "single" |
| // (aka non-multi) installation or we are the Chrome Binaries. |
| - std::vector<base::FilePath> local_state_folders; |
| - GetLocalStateFolders(product, &local_state_folders); |
| - base::FilePath backup_state_file(BackupLocalStateFile(local_state_folders)); |
| + base::FilePath user_data_dir(GetUserDataDir(product)); |
| + base::FilePath backup_state_file(BackupLocalStateFile(user_data_dir)); |
| if (product.is_chrome_app_host()) { |
| DeleteAppHostFilesAndFolders(installer_state, product_state->version()); |
| @@ -1350,7 +1331,7 @@ InstallStatus UninstallProduct(const InstallationState& original_state, |
| } |
| if (delete_profile) |
| - DeleteLocalState(local_state_folders, product.is_chrome_frame()); |
| + DeleteUserDataDir(user_data_dir, product.is_chrome_frame()); |
| if (!force_uninstall) { |
| VLOG(1) << "Uninstallation complete. Launching post-uninstall operations."; |