summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-02 19:53:46 +0000
committerrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-02 19:53:46 +0000
commit4d0f36e5227612dacc8e3d8b5c8e3ff44d0a5869 (patch)
tree9111811103f24e9c98623944cbf6936afc6e88ea
parentf726b1a863b6558b1c5f0886420fe9a2d1ac570c (diff)
downloadchromium_src-4d0f36e5227612dacc8e3d8b5c8e3ff44d0a5869.zip
chromium_src-4d0f36e5227612dacc8e3d8b5c8e3ff44d0a5869.tar.gz
chromium_src-4d0f36e5227612dacc8e3d8b5c8e3ff44d0a5869.tar.bz2
Reverting 27876.
Review URL: http://codereview.chromium.org/256043 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@27880 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/installer/installer.gyp3
-rw-r--r--chrome/installer/setup/install.cc12
-rw-r--r--chrome/installer/setup/setup_main.cc46
-rw-r--r--chrome/installer/setup/uninstall.cc62
-rw-r--r--chrome/installer/util/delete_after_reboot_helper.cc375
-rw-r--r--chrome/installer/util/delete_after_reboot_helper.h66
-rw-r--r--chrome/installer/util/delete_after_reboot_helper_unittest.cc184
-rw-r--r--chrome/installer/util/util_constants.h3
8 files changed, 17 insertions, 734 deletions
diff --git a/chrome/installer/installer.gyp b/chrome/installer/installer.gyp
index df05ed1..b49f877 100644
--- a/chrome/installer/installer.gyp
+++ b/chrome/installer/installer.gyp
@@ -41,8 +41,6 @@
'util/create_dir_work_item.h',
'util/create_reg_key_work_item.cc',
'util/create_reg_key_work_item.h',
- 'util/delete_after_reboot_helper.cc',
- 'util/delete_after_reboot_helper.h',
'util/delete_reg_value_work_item.cc',
'util/delete_reg_value_work_item.h',
'util/delete_tree_work_item.cc',
@@ -152,7 +150,6 @@
'util/copy_tree_work_item_unittest.cc',
'util/create_dir_work_item_unittest.cc',
'util/create_reg_key_work_item_unittest.cc',
- 'util/delete_after_reboot_helper_unittest.cc',
'util/delete_reg_value_work_item_unittest.cc',
'util/delete_tree_work_item_unittest.cc',
'util/google_chrome_distribution_unittest.cc',
diff --git a/chrome/installer/setup/install.cc b/chrome/installer/setup/install.cc
index 1bc8164..24d2f80 100644
--- a/chrome/installer/setup/install.cc
+++ b/chrome/installer/setup/install.cc
@@ -15,7 +15,6 @@
#include "chrome/installer/setup/setup_constants.h"
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/create_reg_key_work_item.h"
-#include "chrome/installer/util/delete_after_reboot_helper.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/helper.h"
#include "chrome/installer/util/install_util.h"
@@ -96,7 +95,7 @@ void AddUninstallShortcutWorkItems(HKEY reg_root,
uninstall_cmd.append(L"\" --");
uninstall_cmd.append(installer_util::switches::kUninstall);
-#if defined(CHROME_FRAME_BUILD)
+#ifdef CHROME_FRAME_BUILD
uninstall_cmd.append(L" --");
uninstall_cmd.append(installer_util::switches::kForceUninstall);
uninstall_cmd.append(L" --");
@@ -247,7 +246,7 @@ bool CreateOrUpdateChromeShortcuts(const std::wstring& exe_path,
std::wstring arguments(L" --");
arguments.append(installer_util::switches::kUninstall);
-#if defined(CHROME_FRAME_BUILD)
+#ifdef CHROME_FRAME_BUILD
arguments.append(L" --");
arguments.append(installer_util::switches::kForceUninstall);
arguments.append(L" --");
@@ -460,13 +459,6 @@ bool InstallNewVersion(const std::wstring& exe_path,
if (reg_root != HKEY_LOCAL_MACHINE && reg_root != HKEY_CURRENT_USER)
return false;
-#if defined(CHROME_FRAME_BUILD)
- // Make sure that we don't end up deleting installed files on next reboot.
- if (!RemoveFromMovesPendingReboot(install_path.c_str())) {
- LOG(ERROR) << "Error accessing pending moves value.";
- }
-#endif
-
scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList());
// A temp directory that work items need and the actual install directory.
install_list->AddCreateDirWorkItem(FilePath::FromWStringHack(temp_dir));
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
index 3b5377d..8b70a1b 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.cc
@@ -5,7 +5,6 @@
#include <string>
#include <windows.h>
#include <msi.h>
-#include <shellapi.h>
#include <shlobj.h>
#include "base/at_exit.h"
@@ -14,7 +13,6 @@
#include "base/file_util.h"
#include "base/path_service.h"
#include "base/registry.h"
-#include "base/scoped_handle_win.h"
#include "base/string_util.h"
#include "base/win_util.h"
#include "chrome/installer/setup/install.h"
@@ -415,7 +413,7 @@ bool HandleNonInstallCmdLineOptions(const CommandLine& cmd_line,
exit_code = ShowEULADialog(inner_frame);
if (installer_util::EULA_REJECTED != exit_code)
GoogleUpdateSettings::SetEULAConsent(true);
- return true;
+ return true;;
} else if (cmd_line.HasSwitch(
installer_util::switches::kRegisterChromeBrowser)) {
// If --register-chrome-browser option is specified, register all
@@ -466,40 +464,6 @@ bool HandleNonInstallCmdLineOptions(const CommandLine& cmd_line,
return false;
}
-bool ShowRebootDialog() {
- // Get a token for this process.
- HANDLE token;
- if (!OpenProcessToken(GetCurrentProcess(),
- TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
- &token)) {
- LOG(ERROR) << "Failed to open token.";
- return false;
- }
-
- // Use a ScopedHandle to keep track of and eventually close our handle.
- // TODO(robertshield): Add a Receive() method to base's ScopedHandle.
- ScopedHandle scoped_handle(token);
-
- // Get the LUID for the shutdown privilege.
- TOKEN_PRIVILEGES tkp = {0};
- LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
- tkp.PrivilegeCount = 1;
- tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
-
- // Get the shutdown privilege for this process.
- AdjustTokenPrivileges(token, FALSE, &tkp, 0,
- reinterpret_cast<PTOKEN_PRIVILEGES>(NULL), 0);
- if (GetLastError() != ERROR_SUCCESS) {
- LOG(ERROR) << "Unable to get shutdown privileges.";
- return false;
- }
-
- // Popup a dialog that will prompt to reboot using the default system message.
- // TODO(robertshield): Add a localized, more specific string to the prompt.
- RestartDialog(NULL, NULL, EWX_REBOOT | EWX_FORCEIFHUNG);
- return true;
-}
-
} // namespace
int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance,
@@ -586,15 +550,7 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance,
prefs.get());
}
- if (install_status == installer_util::UNINSTALL_REQUIRES_REBOOT) {
- install_status = installer_util::UNINSTALL_SUCCESSFUL;
-#if defined(CHROME_FRAME_BUILD)
- ShowRebootDialog();
-#endif
- }
-
CoUninitialize();
-
BrowserDistribution* dist = BrowserDistribution::GetDistribution();
return dist->GetInstallReturnCode(install_status);
}
diff --git a/chrome/installer/setup/uninstall.cc b/chrome/installer/setup/uninstall.cc
index 2ad8cf2..978c056 100644
--- a/chrome/installer/setup/uninstall.cc
+++ b/chrome/installer/setup/uninstall.cc
@@ -17,7 +17,6 @@
#include "chrome/installer/setup/install.h"
#include "chrome/installer/setup/setup_constants.h"
#include "chrome/installer/util/browser_distribution.h"
-#include "chrome/installer/util/delete_after_reboot_helper.h"
#include "chrome/installer/util/helper.h"
#include "chrome/installer/util/install_util.h"
#include "chrome/installer/util/logging_installer.h"
@@ -138,27 +137,18 @@ bool DeleteEmptyParentDir(const std::wstring& path) {
return ret;
}
-enum DeleteResult {
- DELETE_SUCCEEDED,
- DELETE_FAILED,
- DELETE_REQUIRES_REBOOT
-};
-
-// Deletes all installed files of Chromium and Folders or schedules them for
-// deletion on reboot if they are in use. Before deleting it
+// Deletes all installed files of Chromium and Folders. Before deleting it
// needs to move setup.exe in a temp folder because the current process
-// is using that file.
-// Returns DELETE_SUCCEEDED if all files were successfully delete.
-// Returns DELETE_FAILED if it could not get the path to the install dir.
-// Returns DELETE_REQUIRES_REBOOT if the files were in use and so were
-// scheduled for deletion on next reboot.
-DeleteResult DeleteFilesAndFolders(const std::wstring& exe_path,
- bool system_uninstall, const installer::Version& installed_version,
+// is using that file. It returns false when it can not get the path to
+// installation folder, in all other cases it returns true even in case
+// of error (only logs the error).
+bool DeleteFilesAndFolders(const std::wstring& exe_path, bool system_uninstall,
+ const installer::Version& installed_version,
std::wstring* local_state_path, bool delete_profile) {
std::wstring install_path(installer::GetChromeInstallPath(system_uninstall));
if (install_path.empty()) {
LOG(ERROR) << "Could not get installation destination path.";
- return DELETE_FAILED; // Nothing else we can do to uninstall, so we return.
+ return false; // Nothing else we can do for uninstall, so we return.
} else {
LOG(INFO) << "install destination path: " << install_path;
}
@@ -189,46 +179,27 @@ DeleteResult DeleteFilesAndFolders(const std::wstring& exe_path,
file_util::CopyFile(user_local_file, path);
}
- DeleteResult result = DELETE_SUCCEEDED;
-
LOG(INFO) << "Deleting install path " << install_path;
if (!file_util::Delete(install_path, true)) {
LOG(ERROR) << "Failed to delete folder (1st try): " << install_path;
-#if defined(CHROME_FRAME_BUILD)
- // We don't try killing Chrome processes for Chrome Frame builds since
- // that is unlikely to help. Instead, schedule files for deletion and
- // return a value that will trigger a reboot prompt.
- ScheduleDirectoryForDeletion(install_path.c_str());
- result = DELETE_REQUIRES_REBOOT;
-#else
// Try closing any running chrome processes and deleting files once again.
CloseAllChromeProcesses();
- if (!file_util::Delete(install_path, true)) {
+ if (!file_util::Delete(install_path, true))
LOG(ERROR) << "Failed to delete folder (2nd try): " << install_path;
- result = DELETE_FAILED;
- }
-#endif
}
if (delete_profile) {
LOG(INFO) << "Deleting user profile" << user_local_state.value();
- if (!file_util::Delete(user_local_state, true)) {
- LOG(ERROR) << "Failed to delete user profile dir: "
+ if (!file_util::Delete(user_local_state, true))
+ LOG(ERROR) << "Failed to delete user profle dir: "
<< user_local_state.value();
-#if defined(CHROME_FRAME_BUILD)
- ScheduleDirectoryForDeletion(user_local_state.value().c_str());
- result = DELETE_REQUIRES_REBOOT;
-#else
- result = DELETE_FAILED;
-#endif
- }
DeleteEmptyParentDir(user_local_state.value());
}
// Now check and delete if the parent directories are empty
// For example Google\Chrome or Chromium
DeleteEmptyParentDir(install_path);
- return result;
+ return true;
}
// This method tries to delete a registry key and logs an error message
@@ -397,9 +368,7 @@ installer_util::InstallStatus installer_setup::UninstallChrome(
if (force_uninstall) {
// Since --force-uninstall command line option is used, we are going to
// do silent uninstall. Try to close all running Chrome instances.
-#if !defined(CHROME_FRAME_BUILD)
CloseAllChromeProcesses();
-#endif
} else { // no --force-uninstall so lets show some UI dialog boxes.
status = IsChromeActiveOrUserCancelled(system_uninstall);
if (status != installer_util::UNINSTALL_CONFIRMED &&
@@ -500,14 +469,9 @@ installer_util::InstallStatus installer_setup::UninstallChrome(
(cmd_line.HasSwitch(installer_util::switches::kDeleteProfile));
std::wstring local_state_path;
ret = installer_util::UNINSTALL_SUCCESSFUL;
-
- DeleteResult delete_result = DeleteFilesAndFolders(exe_path,
- system_uninstall, *installed_version, &local_state_path, delete_profile);
- if (delete_result == DELETE_FAILED) {
+ if (!DeleteFilesAndFolders(exe_path, system_uninstall, *installed_version,
+ &local_state_path, delete_profile))
ret = installer_util::UNINSTALL_FAILED;
- } else if (delete_result == DELETE_REQUIRES_REBOOT) {
- ret = installer_util::UNINSTALL_REQUIRES_REBOOT;
- }
if (!force_uninstall) {
LOG(INFO) << "Uninstallation complete. Launching Uninstall survey.";
diff --git a/chrome/installer/util/delete_after_reboot_helper.cc b/chrome/installer/util/delete_after_reboot_helper.cc
deleted file mode 100644
index a54acb3..0000000
--- a/chrome/installer/util/delete_after_reboot_helper.cc
+++ /dev/null
@@ -1,375 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// This file defines helper methods used to schedule files for deletion
-// on next reboot. The code here is heavily borrowed and simplified from
-// http://code.google.com/p/omaha/source/browse/trunk/common/file.cc and
-// http://code.google.com/p/omaha/source/browse/trunk/common/utils.cc
-//
-// This implementation really is not fast, so do not use it where that will
-// matter.
-
-#include "chrome/installer/util/delete_after_reboot_helper.h"
-
-#include <string>
-#include <vector>
-
-#include "base/file_util.h"
-#include "base/registry.h"
-#include "base/string_util.h"
-
-// The moves-pending-reboot is a MULTISZ registry key in the HKLM part of the
-// registry.
-const wchar_t kSessionManagerKey[] =
- L"SYSTEM\\CurrentControlSet\\Control\\Session Manager";
-const wchar_t kPendingFileRenameOps[] = L"PendingFileRenameOperations";
-
-namespace {
-
-// Returns true if this directory name is 'safe' for deletion (doesn't contain
-// "..", doesn't specify a drive root)
-bool IsSafeDirectoryNameForDeletion(const wchar_t* dir_name) {
- DCHECK(dir_name);
-
- // empty name isn't allowed
- if (!(dir_name && *dir_name)) {
- return false;
- }
-
- // require a character other than \/:. after the last :
- // disallow anything with ".."
- bool ok = false;
- for (const wchar_t* s = dir_name; *s; ++s) {
- if (*s != L'\\' && *s != L'/' && *s != L':' && *s != L'.') {
- ok = true;
- }
- if (*s == L'.' && s > dir_name && *(s - 1) == L'.') {
- return false;
- }
- if (*s == L':') {
- ok = false;
- }
- }
- return ok;
-}
-
-// Must only be called for regular files or directories that will be empty.
-bool ScheduleFileSystemEntityForDeletion(const wchar_t* path) {
- // Check if the file exists, return false if not.
- WIN32_FILE_ATTRIBUTE_DATA attrs = {0};
- if (!::GetFileAttributesEx(path, ::GetFileExInfoStandard, &attrs)) {
- LOG(ERROR) << path << " for deletion does not exist." << GetLastError();
- return false;
- }
-
- DWORD flags = MOVEFILE_DELAY_UNTIL_REBOOT;
- if (!file_util::DirectoryExists(path)) {
- // This flag valid only for files
- flags |= MOVEFILE_REPLACE_EXISTING;
- }
-
- if (!::MoveFileEx(path, NULL, flags)) {
- LOG(ERROR) << "Could not schedule " << path << " for deletion.";
- return false;
- }
-
- LOG(INFO) << "Scheduled for deletion: " << path;
- return true;
-}
-} // end namespace
-
-bool ScheduleDirectoryForDeletion(const wchar_t* dir_name) {
- if (!IsSafeDirectoryNameForDeletion(dir_name)) {
- LOG(ERROR) << "Unsafe directory name for deletion: " << dir_name;
- return false;
- }
-
- // Make sure the directory exists (it is ok if it doesn't)
- DWORD dir_attributes = ::GetFileAttributes(dir_name);
- if (dir_attributes == INVALID_FILE_ATTRIBUTES) {
- if (::GetLastError() == ERROR_FILE_NOT_FOUND) {
- return true; // Ok if directory is missing
- } else {
- LOG(ERROR) << "Could not GetFileAttributes for " << dir_name;
- return false;
- }
- }
- // Confirm it is a directory
- if (!(dir_attributes & FILE_ATTRIBUTE_DIRECTORY)) {
- LOG(ERROR) << "Scheduled directory is not a directory: " << dir_name;
- return false;
- }
-
- // First schedule all the normal files for deletion.
- {
- bool success = true;
- file_util::FileEnumerator file_enum(FilePath(dir_name), false,
- file_util::FileEnumerator::FILES);
- for (FilePath file = file_enum.Next(); !file.empty();
- file = file_enum.Next()) {
- success = ScheduleFileSystemEntityForDeletion(file.value().c_str());
- if (!success) {
- LOG(ERROR) << "Failed to schedule file for deletion: " << file.value();
- return false;
- }
- }
- }
-
- // Then recurse to all the subdirectories.
- {
- bool success = true;
- file_util::FileEnumerator dir_enum(FilePath(dir_name), false,
- file_util::FileEnumerator::DIRECTORIES);
- for (FilePath sub_dir = dir_enum.Next(); !sub_dir.empty();
- sub_dir = dir_enum.Next()) {
- success = ScheduleDirectoryForDeletion(sub_dir.value().c_str());
- if (!success) {
- LOG(ERROR) << "Failed to schedule subdirectory for deletion: "
- << sub_dir.value();
- return false;
- }
- }
- }
-
- // Now schedule the empty directory itself
- if (!ScheduleFileSystemEntityForDeletion(dir_name)) {
- LOG(ERROR) << "Failed to schedule directory for deletion: " << dir_name;
- }
-
- return true;
-}
-
-// Converts the strings found in |buffer| to a list of wstrings that is returned
-// in |value|.
-// |buffer| points to a series of pairs of null-terminated wchar_t strings
-// followed by a terminating null character.
-// |byte_count| is the length of |buffer| in bytes.
-// |value| is a pointer to an empty vector of wstrings. On success, this vector
-// contains all of the strings extracted from |buffer|.
-// Returns S_OK on success, E_INVALIDARG if buffer does not meet tha above
-// specification.
-HRESULT MultiSZBytesToStringArray(const char* buffer, size_t byte_count,
- std::vector<PendingMove>* value) {
- DCHECK(buffer);
- DCHECK(value);
- DCHECK(value->empty());
-
- DWORD data_len = byte_count / sizeof(wchar_t);
- const wchar_t* data = reinterpret_cast<const wchar_t*>(buffer);
- const wchar_t* data_end = data + data_len;
- if (data_len > 1) {
- // must be terminated by two null characters
- if (data[data_len - 1] != 0 || data[data_len - 2] != 0) {
- DLOG(ERROR) << "Invalid MULTI_SZ found.";
- return E_INVALIDARG;
- }
-
- // put null-terminated strings into arrays
- while (data < data_end) {
- std::wstring str_from(data);
- data += str_from.length() + 1;
- if (data < data_end) {
- std::wstring str_to(data);
- data += str_to.length() + 1;
- value->push_back(std::make_pair(str_from, str_to));
- }
- }
- }
- return S_OK;
-}
-
-void StringArrayToMultiSZBytes(const std::vector<PendingMove>& strings,
- std::vector<char>* buffer) {
- DCHECK(buffer);
- buffer->clear();
-
- if (strings.size() == 0) {
- // Leave buffer empty if we have no strings.
- return;
- }
-
- size_t total_wchars = 0;
- {
- std::vector<PendingMove>::const_iterator iter(strings.begin());
- for (; iter != strings.end(); ++iter) {
- total_wchars += iter->first.length();
- total_wchars++; // Space for the null char.
- total_wchars += iter->second.length();
- total_wchars++; // Space for the null char.
- }
- total_wchars++; // Space for the extra terminating null char.
- }
-
- size_t total_length = total_wchars * sizeof(wchar_t);
- buffer->resize(total_length);
- wchar_t* write_pointer = reinterpret_cast<wchar_t*>(&((*buffer)[0]));
- // Keep an end pointer around for sanity checking.
- wchar_t* end_pointer = write_pointer + total_wchars;
-
- std::vector<PendingMove>::const_iterator copy_iter(strings.begin());
- for (; copy_iter != strings.end() && write_pointer < end_pointer;
- copy_iter++) {
- // First copy the source string.
- size_t string_length = copy_iter->first.length() + 1;
- memcpy(write_pointer, copy_iter->first.c_str(),
- string_length * sizeof(wchar_t));
- write_pointer += string_length;
- // Now copy the destination string.
- string_length = copy_iter->second.length() + 1;
- memcpy(write_pointer, copy_iter->second.c_str(),
- string_length * sizeof(wchar_t));
- write_pointer += string_length;
-
- // We should never run off the end while in this loop.
- DCHECK(write_pointer < end_pointer);
- }
- *write_pointer = L'\0'; // Explicitly set the final null char.
- DCHECK(++write_pointer == end_pointer);
-}
-
-std::wstring GetShortPathName(const wchar_t* path) {
- std::wstring short_path;
- DWORD length = GetShortPathName(path, WriteInto(&short_path, MAX_PATH),
- MAX_PATH);
- DLOG_IF(WARNING, length == 0) << __FUNCTION__ << " gle=" << GetLastError();
- short_path.resize(length);
- return short_path;
-}
-
-HRESULT GetPendingMovesValue(
- std::vector<PendingMove>* pending_moves) {
- DCHECK(pending_moves);
- pending_moves->clear();
-
- // Get the current value of the key
- // If the Key is missing, that's totally acceptable.
- RegKey session_manager_key(HKEY_LOCAL_MACHINE, kSessionManagerKey,
- KEY_QUERY_VALUE);
- HKEY session_manager_handle = session_manager_key.Handle();
- if (!session_manager_handle) {
- return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
- }
-
- // The base::RegKey Read code squashes the return code from
- // ReqQueryValueEx, we have to do things ourselves:
- DWORD buffer_size = 0;
- std::vector<char> buffer;
- buffer.resize(1);
- DWORD type;
- DWORD result = RegQueryValueEx(session_manager_handle, kPendingFileRenameOps,
- 0, &type, reinterpret_cast<BYTE*>(&buffer[0]),
- &buffer_size);
-
- if (result == ERROR_FILE_NOT_FOUND) {
- // No pending moves were found.
- return HRESULT_FROM_WIN32(result);
- } else if (result == ERROR_MORE_DATA) {
- if (type != REG_MULTI_SZ) {
- DLOG(ERROR) << "Found PendingRename value of unexpected type.";
- return E_UNEXPECTED;
- }
- if (buffer_size % 2) {
- // The buffer size should be an even number (since we expect wchar_ts).
- // If this is not the case, fail here.
- DLOG(ERROR) << "Corrupt PendingRename value.";
- return E_UNEXPECTED;
- }
-
- // There are pending file renames. Read them in.
- buffer.resize(buffer_size);
- result = RegQueryValueEx(session_manager_handle, kPendingFileRenameOps,
- 0, &type, reinterpret_cast<LPBYTE>(&buffer[0]),
- &buffer_size);
- if (result != ERROR_SUCCESS) {
- DLOG(ERROR) << "Failed to read from " << kPendingFileRenameOps;
- return HRESULT_FROM_WIN32(result);
- }
- } else {
- // That was unexpected.
- DLOG(ERROR) << "Unexpected result from RegQueryValueEx: " << result;
- return HRESULT_FROM_WIN32(result);
- }
-
- // We now have a buffer of bytes that is actually a sequence of
- // null-terminated wchar_t strings terminated by an additional null character.
- // Stick this into a vector of strings for clarity.
- HRESULT hr = MultiSZBytesToStringArray(&buffer[0], buffer.size(),
- pending_moves);
- return hr;
-}
-
-bool MatchPendingDeletePath(const std::wstring& short_form_needle,
- const std::wstring& reg_path) {
- std::wstring match_path(reg_path); // Stores the path stored in each entry.
-
- // First chomp the prefix since that will mess up GetShortPathName.
- std::wstring prefix(L"\\??\\");
- if (StartsWith(match_path, prefix, false)) {
- match_path = match_path.substr(4);
- }
-
- // Get the short path name of the entry.
- std::wstring short_match_path(GetShortPathName(match_path.c_str()));
-
- // Now compare the paths. If it isn't one we're looking for, add it
- // to the list to keep.
- return StartsWith(short_match_path, short_form_needle, false);
-}
-
-// Removes all pending moves for the given |directory| and any contained
-// files or subdirectories. Returns true on success
-bool RemoveFromMovesPendingReboot(const wchar_t* directory) {
- DCHECK(directory);
- std::vector<PendingMove> pending_moves;
- HRESULT hr = GetPendingMovesValue(&pending_moves);
- if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) {
- // No pending moves, nothing to do.
- return true;
- } else if (FAILED(hr)) {
- // Couldn't read the key or the key was corrupt.
- return false;
- }
-
- // Get the short form of |directory| and use that to match.
- std::wstring short_directory(GetShortPathName(directory));
-
- std::vector<PendingMove> strings_to_keep;
- std::vector<PendingMove>::const_iterator iter(pending_moves.begin());
- for (; iter != pending_moves.end(); iter++) {
- if (!MatchPendingDeletePath(short_directory, iter->first)) {
- // This doesn't match the deletions we are looking for. Preserve
- // this string pair, making sure that it is in fact a pair.
- strings_to_keep.push_back(*iter);
- }
- }
-
- if (strings_to_keep.size() == pending_moves.size()) {
- // Nothing to remove, return true.
- return true;
- }
-
- // Write the key back into a buffer.
- RegKey session_manager_key(HKEY_LOCAL_MACHINE, kSessionManagerKey,
- KEY_CREATE_SUB_KEY | KEY_SET_VALUE);
- if (!session_manager_key.Handle()) {
- // Couldn't open / create the key.
- LOG(ERROR) << "Failed to open session manager key for writing.";
- return false;
- }
-
- if (strings_to_keep.size() > 1) {
- std::vector<char> buffer;
- StringArrayToMultiSZBytes(strings_to_keep, &buffer);
- DCHECK(buffer.size() > 0);
- if (buffer.size() > 0) {
- return session_manager_key.WriteValue(kPendingFileRenameOps, &buffer[0],
- buffer.size(), REG_MULTI_SZ);
- } else {
- return false;
- }
- } else {
- // We have only the trailing NULL string. Don't bother writing that.
- return session_manager_key.DeleteValue(kPendingFileRenameOps);
- }
-}
diff --git a/chrome/installer/util/delete_after_reboot_helper.h b/chrome/installer/util/delete_after_reboot_helper.h
deleted file mode 100644
index 064a634..0000000
--- a/chrome/installer/util/delete_after_reboot_helper.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// This file declares helper methods used to schedule files for deletion
-// on next reboot.
-
-#ifndef CHROME_INSTALLER_UTIL_DELETE_AFTER_REBOOT_HELPER_H_
-#define CHROME_INSTALLER_UTIL_DELETE_AFTER_REBOOT_HELPER_H_
-
-#include <string>
-#include <vector>
-
-#include <windows.h>
-
-// Used by the unit tests.
-extern const wchar_t kSessionManagerKey[];
-extern const wchar_t kPendingFileRenameOps[];
-
-typedef std::pair<std::wstring, std::wstring> PendingMove;
-
-// Attempts to schedule the directory for deletion.
-bool ScheduleDirectoryForDeletion(const wchar_t* dir_name);
-
-// Removes all pending moves that are registered for |directory| and all
-// elements contained in |directory|.
-bool RemoveFromMovesPendingReboot(const wchar_t* directory);
-
-// Retrieves the list of pending renames from the registry and returns a vector
-// containing pairs of strings that represent the operations. If the list
-// contains only deletes then every other element will be an empty string
-// as per http://msdn.microsoft.com/en-us/library/aa365240(VS.85).aspx.
-HRESULT GetPendingMovesValue(std::vector<PendingMove>* pending_moves);
-
-// This returns true if |short_form_needle| is contained in |reg_path| where
-// |short_form_needle| is a file system path that has been shortened by
-// GetShortPathName and |reg_path| is a path stored in the
-// PendingFileRenameOperations key.
-bool MatchPendingDeletePath(const std::wstring& short_form_needle,
- const std::wstring& reg_path);
-
-// Converts the strings found in |buffer| to a list of PendingMoves that is
-// returned in |value|.
-// |buffer| points to a series of pairs of null-terminated wchar_t strings
-// followed by a terminating null character.
-// |byte_count| is the length of |buffer| in bytes.
-// |value| is a pointer to an empty vector of PendingMoves (string pairs).
-// On success, this vector contains all of the string pairs extracted from
-// |buffer|.
-// Returns S_OK on success, E_INVALIDARG if buffer does not meet the above
-// specification.
-HRESULT MultiSZBytesToStringArray(const char* buffer, size_t byte_count,
- std::vector<PendingMove>* value);
-
-// The inverse of MultiSZBytesToStringArray, this function converts a list
-// of string pairs into a byte array format suitable for writing to the
-// kPendingFileRenameOps registry value. It concatenates the strings and
-// appends an additional terminating null character.
-void StringArrayToMultiSZBytes(const std::vector<PendingMove>& strings,
- std::vector<char>* buffer);
-
-// A helper function for the win32 GetShortPathName that more conveniently
-// returns a correctly sized wstring.
-std::wstring GetShortPathName(const wchar_t* path);
-
-#endif // CHROME_INSTALLER_UTIL_DELETE_AFTER_REBOOT_HELPER_H_
diff --git a/chrome/installer/util/delete_after_reboot_helper_unittest.cc b/chrome/installer/util/delete_after_reboot_helper_unittest.cc
deleted file mode 100644
index bf5af3b..0000000
--- a/chrome/installer/util/delete_after_reboot_helper_unittest.cc
+++ /dev/null
@@ -1,184 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <windows.h>
-#include <shlobj.h>
-
-#include "base/file_util.h"
-#include "base/registry.h"
-#include "base/scoped_ptr.h"
-#include "base/string_util.h"
-#include "chrome/installer/util/delete_after_reboot_helper.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-// These tests exercise the Delete-After-Reboot code which requires
-// modifications to HKLM. This will fail on Vista and above if the user
-// is not an admin or if UAC is on.
-// I tried using RegOverridePredefKey to test, but MoveFileEx ignore this
-// even on 32 bit machines :-( As such, running this test may pollute
-// your PendingFileRenameOperations value.
-class DeleteAfterRebootHelperTest : public testing::Test {
- protected:
- virtual void SetUp() {
- // Create a temporary directory for testing and fill it with some files.
- std::wstring no_prefix;
- file_util::CreateNewTempDirectory(no_prefix, &temp_dir_);
- file_util::CreateTemporaryFileInDir(temp_dir_, &temp_file_);
-
- temp_subdir_ = temp_dir_.Append(L"subdir");
- file_util::CreateDirectory(temp_subdir_);
- file_util::CreateTemporaryFileInDir(temp_subdir_, &temp_subdir_file_);
-
- // Copy the current pending moves and then clear it if we can:
- if (IsUserAnAdmin()) {
- GetPendingMovesValue(&original_pending_moves_);
- }
- }
- virtual void TearDown() {
- // Delete the temporary directory if it's still there.
- file_util::Delete(temp_dir_, true);
-
- // Try and restore the pending moves value, if we have one.
- if (IsUserAnAdmin() && original_pending_moves_.size() > 1) {
- RegKey session_manager_key(HKEY_LOCAL_MACHINE, kSessionManagerKey,
- KEY_CREATE_SUB_KEY | KEY_SET_VALUE);
- if (!session_manager_key.Handle()) {
- // Couldn't open / create the key.
- DLOG(ERROR) << "Failed to open session manager key for writing.";
- }
-
- std::vector<char> buffer;
- StringArrayToMultiSZBytes(original_pending_moves_, &buffer);
- session_manager_key.WriteValue(kPendingFileRenameOps, &buffer[0],
- buffer.size(), REG_MULTI_SZ);
- }
- }
-
- // Compares two buffers of size len. Returns true if they are equal,
- // false otherwise. Standard warnings about making sure the buffers
- // are at least len chars long apply.
- template<class Type>
- bool CompareBuffers(Type* buf1, Type* buf2, int len) {
- Type* comp1 = buf1;
- Type* comp2 = buf2;
- for (int i = 0; i < len; i++) {
- if (*comp1 != *comp2)
- return false;
- comp1++;
- comp2++;
- }
- return true;
- }
-
- // Returns the size of the given list of wstrings in bytes, including
- // null chars, plus an additional terminating null char.
- // e.g. the length of all the strings * sizeof(wchar_t).
- virtual size_t WStringPairListSize(
- const std::vector<PendingMove>& string_list) {
- size_t length = 0;
- std::vector<PendingMove>::const_iterator iter(string_list.begin());
- for (; iter != string_list.end(); ++iter) {
- length += iter->first.size() + 1; // +1 for the null char.
- length += iter->second.size() + 1; // +1 for the null char.
- }
- length++; // for the additional null char.
- return length * sizeof(wchar_t);
- }
-
- std::vector<PendingMove> original_pending_moves_;
-
- FilePath temp_dir_;
- FilePath temp_file_;
- FilePath temp_subdir_;
- FilePath temp_subdir_file_;
-};
-}
-
-TEST_F(DeleteAfterRebootHelperTest, TestStringListToMultiSZConversions) {
- struct StringTest {
- wchar_t* test_name;
- wchar_t* str;
- DWORD length;
- size_t count;
- } tests[] = {
- { L"basic", L"foo\0bar\0fee\0bee\0boo\0bong\0\0", 26 * sizeof(wchar_t), 3 },
- { L"empty", L"\0\0", 2 * sizeof(wchar_t), 1 },
- { L"deletes", L"foo\0\0bar\0\0bizz\0\0", 16 * sizeof(wchar_t), 3 },
- };
-
- for (int i = 0; i < arraysize(tests); i++) {
- std::vector<PendingMove> string_list;
- EXPECT_TRUE(SUCCEEDED(
- MultiSZBytesToStringArray(reinterpret_cast<char*>(tests[i].str),
- tests[i].length, &string_list)))
- << tests[i].test_name;
- EXPECT_EQ(tests[i].count, string_list.size()) << tests[i].test_name;
- std::vector<char> buffer;
- buffer.resize(WStringPairListSize(string_list));
- StringArrayToMultiSZBytes(string_list, &buffer);
- EXPECT_TRUE(CompareBuffers(&buffer[0],
- reinterpret_cast<char*>(tests[i].str),
- tests[i].length)) << tests[i].test_name;
- }
-
- StringTest failures[] =
- { L"malformed", reinterpret_cast<wchar_t*>("oddnumb\0\0"), 9, 1 };
-
- for (int i = 0; i < arraysize(failures); i++) {
- std::vector<PendingMove> string_list;
- EXPECT_FALSE(SUCCEEDED(
- MultiSZBytesToStringArray(reinterpret_cast<char*>(failures[i].str),
- failures[i].length, &string_list)))
- << failures[i].test_name;
- }
-}
-
-
-TEST_F(DeleteAfterRebootHelperTest, TestFileDeletes) {
- if (!IsUserAnAdmin()) {
- return;
- }
-
- EXPECT_TRUE(ScheduleDirectoryForDeletion(temp_dir_.value().c_str()));
-
- std::vector<PendingMove> pending_moves;
- EXPECT_TRUE(SUCCEEDED(GetPendingMovesValue(&pending_moves)));
-
- // We should see, somewhere in this key, deletion writs for
- // temp_file_, temp_subdir_file_, temp_subdir_ and temp_dir_ in that order.
- EXPECT_TRUE(pending_moves.size() > 3);
-
- // Get the short form of temp_file_ and use that to match.
- std::wstring short_temp_file(GetShortPathName(temp_file_.value().c_str()));
-
- // Scan for the first expected delete.
- std::vector<PendingMove>::const_iterator iter(pending_moves.begin());
- for (; iter != pending_moves.end(); iter++) {
- if (MatchPendingDeletePath(short_temp_file, iter->first))
- break;
- }
-
- // Check that each of the deletes we expect are there in order.
- FilePath expected_paths[] =
- { temp_file_, temp_subdir_file_, temp_subdir_, temp_dir_ };
- for (int i = 0; i < arraysize(expected_paths); i++) {
- EXPECT_FALSE(iter == pending_moves.end());
- if (iter != pending_moves.end()) {
- std::wstring short_path_name(
- GetShortPathName(expected_paths[i].value().c_str()));
- EXPECT_TRUE(MatchPendingDeletePath(short_path_name, iter->first));
- iter++;
- }
- }
-
- // Test that we can remove the pending deletes.
- EXPECT_TRUE(RemoveFromMovesPendingReboot(temp_dir_.value().c_str()));
- EXPECT_TRUE(SUCCEEDED(GetPendingMovesValue(&pending_moves)));
- std::vector<PendingMove>::const_iterator check_iter(pending_moves.begin());
- for (; check_iter != pending_moves.end(); ++check_iter) {
- EXPECT_FALSE(MatchPendingDeletePath(short_temp_file, check_iter->first));
- }
-}
diff --git a/chrome/installer/util/util_constants.h b/chrome/installer/util/util_constants.h
index 61f6805..534d770 100644
--- a/chrome/installer/util/util_constants.h
+++ b/chrome/installer/util/util_constants.h
@@ -39,8 +39,7 @@ enum InstallStatus {
EULA_REJECTED, // EULA dialog was not accepted by user.
EULA_ACCEPTED, // EULA dialog was accepted by user.
EULA_ACCEPTED_OPT_IN, // EULA accepted wtih the crash optin selected.
- INSTALL_DIR_IN_USE, // Installation directory is in use by another process
- UNINSTALL_REQUIRES_REBOOT // Uninstallation required a reboot.
+ INSTALL_DIR_IN_USE // Installation directory is in use by another process
};
namespace switches {