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

Unified Diff: chrome/installer/setup/user_hive_visitor.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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/installer/setup/user_hive_visitor.h ('k') | chrome/installer/setup/user_hive_visitor_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/installer/setup/user_hive_visitor.cc
diff --git a/chrome/installer/setup/user_hive_visitor.cc b/chrome/installer/setup/user_hive_visitor.cc
new file mode 100644
index 0000000000000000000000000000000000000000..ca2d7fe9c1cedf6f71b3a214dbd9f71be1600813
--- /dev/null
+++ b/chrome/installer/setup/user_hive_visitor.cc
@@ -0,0 +1,166 @@
+// Copyright 2016 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 "chrome/installer/setup/user_hive_visitor.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/callback_helpers.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/rand_util.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_piece.h"
+#include "base/win/registry.h"
+#include "chrome/installer/setup/setup_util.h"
+#include "chrome/installer/util/shell_util.h"
+
+namespace installer {
+
+namespace {
+
+// A helper for loading and opening a hive into a random subkey of
+// HKEY_LOCAL_MACHINE.
+class ScopedUserHive {
+ public:
+ explicit ScopedUserHive(const base::FilePath& hive_file);
+ ~ScopedUserHive();
+
+ // Returns true if the hive file was loaded.
+ bool valid() const { return key_.Valid(); }
+
+ // Returns the key at the root of the loaded hive, or nullptr if not valid.
+ base::win::RegKey* key() { return key_.Valid() ? &key_ : nullptr; }
+
+ private:
+ // The randomly-chosen name of the subkey under HKLM where the file is loaded.
+ // If empty, the file is not loaded.
+ base::string16 subkey_name_;
+
+ // The loaded key.
+ base::win::RegKey key_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedUserHive);
+};
+
+ScopedUserHive::ScopedUserHive(const base::FilePath& hive_file) {
+ // Generate a random name for the key at which the file will be loaded.
+ uint8_t buffer[10] = {};
+ base::RandBytes(&buffer[0], arraysize(buffer));
+ subkey_name_ = ShellUtil::ByteArrayToBase32(&buffer[0], arraysize(buffer));
+ DCHECK_EQ(16U, subkey_name_.size());
+
+ LONG result = ::RegLoadKey(HKEY_LOCAL_MACHINE, subkey_name_.c_str(),
+ hive_file.value().c_str());
+ if (result != ERROR_SUCCESS) {
+ // Clear subkey_name_ since the load failed so that an unload will not be
+ // attempted in the dtor.
+ subkey_name_.clear();
+ ::SetLastError(result);
+ PLOG(ERROR) << "Failed loading user hive file \"" << hive_file.value()
+ << "\"";
+ return;
+ }
+
+ // Open the newly-loaded key.
+ result = key_.Open(HKEY_LOCAL_MACHINE, subkey_name_.c_str(), KEY_ALL_ACCESS);
+ if (result != ERROR_SUCCESS) {
+ ::SetLastError(result);
+ PLOG(ERROR) << "Failed opening loaded hive file \"" << hive_file.value()
+ << "\"";
+ }
+}
+
+ScopedUserHive::~ScopedUserHive() {
+ key_.Close();
+ if (subkey_name_.empty())
+ return;
+ LONG result = ::RegUnLoadKey(HKEY_LOCAL_MACHINE, subkey_name_.c_str());
+ if (result != ERROR_SUCCESS) {
+ ::SetLastError(result);
+ PLOG(ERROR) << "Failed unloading user hive at \"" << subkey_name_ << "\"";
+ }
+}
+
+bool OpenUserHive(const wchar_t* sid, base::win::RegKey* user_hive) {
+ DCHECK(user_hive);
+ LONG result = user_hive->Open(HKEY_USERS, sid, KEY_ALL_ACCESS);
+ if (result == ERROR_SUCCESS)
+ return true;
+ if (result == ERROR_FILE_NOT_FOUND) {
+ VLOG(1) << "Hive is not loaded for user \"" << sid << "\"";
+ return false;
+ }
+ ::SetLastError(result);
+ PLOG(ERROR) << "Failed opening hive for user \"" << sid << "\"";
+ return false;
+}
+
+} // namespace
+
+void VisitUserHives(const HiveVisitor& visitor) {
+ constexpr wchar_t kProfileListKey[] =
+ L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList";
+
+ // Privileges required to load a registry hive file.
+ ScopedTokenPrivilege se_backup_name_privilege(SE_BACKUP_NAME);
+ ScopedTokenPrivilege se_restore_name_privilege(SE_RESTORE_NAME);
+
+ for (base::win::RegistryKeyIterator iter(HKEY_LOCAL_MACHINE, kProfileListKey);
+ iter.Valid(); ++iter) {
+ const wchar_t* sid = iter.Name();
+ // First try to access the user hive pre-mounted by the OS.
+ VLOG(1) << "Checking for pre-loaded hive for local account \"" << sid
+ << "\"";
+ base::win::RegKey key;
+ if (OpenUserHive(sid, &key)) {
+ VLOG(1) << "Found loaded hive for sid \"" << sid << "\"";
+ if (!visitor.Run(sid, &key))
+ break;
+ continue;
+ }
+
+ // Read the path to the profile directory to load the hive manually.
+ base::string16 profile_key_name(kProfileListKey);
+ profile_key_name.append(1, L'\\').append(sid);
+ LONG result =
+ key.Open(HKEY_LOCAL_MACHINE, profile_key_name.c_str(), KEY_QUERY_VALUE);
+ if (result != ERROR_SUCCESS) {
+ ::SetLastError(result);
+ PLOG(ERROR) << "Failed opening profile key \"" << profile_key_name
+ << "\"";
+ continue;
+ }
+ base::string16 image_path;
+ result = key.ReadValue(L"ProfileImagePath", &image_path);
+ if (result != ERROR_SUCCESS) {
+ ::SetLastError(result);
+ PLOG(ERROR) << "Failed reading ProfileImagePath value of \""
+ << profile_key_name << "\"";
+ }
+ key.Close();
+ if (image_path.empty())
+ continue;
+
+ base::FilePath hive_file(
+ base::FilePath(image_path).Append(FILE_PATH_LITERAL("ntuser.dat")));
+ VLOG(1) << "Falling back to opening \"" << hive_file.value() << "\"";
+ if (!base::PathExists(hive_file)) {
+ VPLOG(1) << "Hive file not found or inaccessible \"" << hive_file.value()
+ << "\"";
+ continue;
+ }
+ ScopedUserHive user_hive(hive_file);
+ if (user_hive.valid()) {
+ VLOG(1) << "Loaded and opened hive for sid \"" << sid << "\"";
+ if (!visitor.Run(sid, user_hive.key()))
+ break;
+ }
+ }
+}
+
+} // namespace installer
« no previous file with comments | « chrome/installer/setup/user_hive_visitor.h ('k') | chrome/installer/setup/user_hive_visitor_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698