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

Side by Side 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: added missing :: 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
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/installer/setup/user_hive_visitor.h"
6
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/callback_helpers.h"
12 #include "base/files/file_path.h"
13 #include "base/files/file_util.h"
14 #include "base/logging.h"
15 #include "base/rand_util.h"
16 #include "base/strings/string16.h"
17 #include "base/strings/string_piece.h"
18 #include "base/win/registry.h"
19 #include "chrome/installer/setup/setup_util.h"
20 #include "chrome/installer/util/shell_util.h"
21
22 namespace installer {
23
24 namespace {
25
26 // A helper for loading and opening a hive into a random subkey of
27 // HKEY_LOCAL_MACHINE.
28 class ScopedUserHive {
29 public:
30 explicit ScopedUserHive(const base::FilePath& hive_file);
31 ~ScopedUserHive();
32
33 // Returns true if the hive file was loaded.
34 bool valid() const { return key_.Valid(); }
35
36 // Returns the key at the root of the loaded hive, or nullptr if not valid.
37 base::win::RegKey* key() { return key_.Valid() ? &key_ : nullptr; }
38
39 private:
40 // The randomly-chosen name of the subkey under HKLM where the file is loaded.
41 // If empty, the file is not loaded.
42 base::string16 subkey_name_;
43
44 // The loaded key.
45 base::win::RegKey key_;
46
47 DISALLOW_COPY_AND_ASSIGN(ScopedUserHive);
48 };
49
50 ScopedUserHive::ScopedUserHive(const base::FilePath& hive_file) {
51 // Generate a random name for the key at which the file will be loaded.
52 uint8_t buffer[10] = {};
53 base::RandBytes(&buffer[0], arraysize(buffer));
54 base::string16 name =
55 ShellUtil::ByteArrayToBase32(&buffer[0], arraysize(buffer));
56 DCHECK_EQ(16U, name.size());
57
58 LONG result =
59 ::RegLoadKey(HKEY_LOCAL_MACHINE, name.c_str(), hive_file.value().c_str());
60 if (result != ERROR_SUCCESS) {
61 ::SetLastError(result);
62 PLOG(ERROR) << "Failed loading user hive file \"" << hive_file.value()
63 << "\"";
64 return;
65 }
66 subkey_name_ = std::move(name);
67
68 // Open the newly-loaded key.
69 result = key_.Open(HKEY_LOCAL_MACHINE, subkey_name_.c_str(), KEY_ALL_ACCESS);
70 if (result != ERROR_SUCCESS) {
71 ::SetLastError(result);
72 PLOG(ERROR) << "Failed opening loaded hive file \"" << hive_file.value()
73 << "\"";
74 }
75 }
76
77 ScopedUserHive::~ScopedUserHive() {
78 key_.Close();
79 if (subkey_name_.empty())
80 return;
81 LONG result = ::RegUnLoadKey(HKEY_LOCAL_MACHINE, subkey_name_.c_str());
82 if (result == ERROR_SUCCESS)
83 return;
84 ::SetLastError(result);
85 PLOG(ERROR) << "Failed unloading user hive at \"" << subkey_name_ << "\"";
86 }
87
88 bool OpenUserHive(const wchar_t* sid, base::win::RegKey* user_hive) {
89 DCHECK(user_hive);
90 LONG result = user_hive->Open(HKEY_USERS, sid, KEY_ALL_ACCESS);
91 if (result == ERROR_SUCCESS)
92 return true;
93 if (result == ERROR_FILE_NOT_FOUND) {
94 VLOG(1) << "Hive is not loaded for user \"" << sid << "\"";
95 return false;
96 }
97 ::SetLastError(result);
98 PLOG(ERROR) << "Failed opening hive for user \"" << sid << "\"";
99 return false;
100 }
101
102 } // namespace
103
104 void VisitUserHives(const HiveVisitor& visitor) {
105 constexpr wchar_t kProfileListKey[] =
106 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList";
107 constexpr wchar_t kProfileImagePathValue[] = L"ProfileImagePath";
108
109 // Privileges required to load a registry hive file.
110 ScopedTokenPrivilege se_backup_name_privilege(SE_BACKUP_NAME);
111 ScopedTokenPrivilege se_restore_name_privilege(SE_RESTORE_NAME);
112
113 for (base::win::RegistryKeyIterator iter(HKEY_LOCAL_MACHINE, kProfileListKey);
114 iter.Valid(); ++iter) {
115 const wchar_t* sid = iter.Name();
116 VLOG(1) << "Found local account \"" << sid << "\".";
117 base::string16 profile_key_name(kProfileListKey);
118 profile_key_name.append(1, L'\\').append(sid);
119 base::win::RegKey key;
120 LONG result =
121 key.Open(HKEY_LOCAL_MACHINE, profile_key_name.c_str(), KEY_QUERY_VALUE);
122 if (result != ERROR_SUCCESS) {
123 ::SetLastError(result);
124 PLOG(ERROR) << "Failed opening profile key \"" << profile_key_name
125 << "\"";
126 continue;
127 }
128
129 // Read the path to the profile directory.
130 base::string16 image_path;
131 result = key.ReadValue(kProfileImagePathValue, &image_path);
gab 2016/06/01 14:34:44 I'd expect keeping L"ProfileImagePath" inline here
grt (UTC plus 2) 2016/06/01 14:40:38 Done.
132 if (result != ERROR_SUCCESS) {
133 ::SetLastError(result);
134 PLOG(ERROR) << "Failed reading ProfileImagePath value of \""
135 << profile_key_name << "\"";
136 }
137
138 // First try to access the user hive pre-mounted by the OS.
139 key.Close();
140 VLOG(1) << "Checking for pre-loaded hive for sid \"" << sid << "\".";
141 if (OpenUserHive(sid, &key)) {
142 VLOG(1) << "Found loaded hive for sid \"" << sid << "\"";
143 if (!visitor.Run(sid, &key))
144 break;
145 continue;
146 }
147
148 // Failing that, try loading the hive manually. The path will be empty if
149 // not present in the registry. Skip this profile in that case.
150 if (image_path.empty())
151 continue;
152
153 base::FilePath hive_file(
154 base::FilePath(image_path).Append(FILE_PATH_LITERAL("ntuser.dat")));
155 VLOG(1) << "Falling back to opening \"" << hive_file.value() << "\"";
156 if (!base::PathExists(hive_file)) {
157 VPLOG(1) << "Hive file not found or inaccessible \"" << hive_file.value()
158 << "\"";
159 continue;
160 }
161 ScopedUserHive user_hive(hive_file);
162 if (user_hive.valid()) {
163 VLOG(1) << "Loaded and opened hive for sid \"" << sid << "\"";
164 if (!visitor.Run(sid, user_hive.key()))
165 break;
166 }
167 }
168 }
169
170 } // namespace installer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698