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

Side by Side Diff: chrome_frame/dll_redirector.cc

Issue 126143005: Remove Chrome Frame code and resources. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: sync to r244038 Created 6 years, 11 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 | Annotate | Revision Log
« no previous file with comments | « chrome_frame/dll_redirector.h ('k') | chrome_frame/event_hooker.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome_frame/dll_redirector.h"
6
7 #include <aclapi.h>
8 #include <atlbase.h>
9 #include <atlsecurity.h>
10 #include <sddl.h>
11
12 #include "base/file_version_info.h"
13 #include "base/files/file_path.h"
14 #include "base/logging.h"
15 #include "base/memory/shared_memory.h"
16 #include "base/path_service.h"
17 #include "base/strings/string_util.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "base/version.h"
20 #include "base/win/windows_version.h"
21 #include "chrome_frame/utils.h"
22
23 const wchar_t kSharedMemoryName[] = L"ChromeFrameVersionBeacon_";
24 const uint32 kSharedMemorySize = 128;
25 const uint32 kSharedMemoryLockTimeoutMs = 1000;
26
27 // static
28 DllRedirector::DllRedirector() : first_module_handle_(NULL) {
29 // TODO(robertshield): Allow for overrides to be taken from the environment.
30 std::wstring beacon_name(kSharedMemoryName);
31 beacon_name += GetHostProcessName(false);
32 shared_memory_.reset(new base::SharedMemory(beacon_name));
33 shared_memory_name_ = base::WideToUTF8(beacon_name);
34 }
35
36 DllRedirector::DllRedirector(const char* shared_memory_name)
37 : shared_memory_name_(shared_memory_name), first_module_handle_(NULL) {
38 shared_memory_.reset(
39 new base::SharedMemory(base::ASCIIToWide(shared_memory_name)));
40 }
41
42 DllRedirector::~DllRedirector() {
43 if (first_module_handle_) {
44 if (first_module_handle_ != reinterpret_cast<HMODULE>(&__ImageBase)) {
45 FreeLibrary(first_module_handle_);
46 } else {
47 NOTREACHED() << "Error, DllRedirector attempting to free self.";
48 }
49
50 first_module_handle_ = NULL;
51 }
52 UnregisterAsFirstCFModule();
53 }
54
55 // static
56 DllRedirector* DllRedirector::GetInstance() {
57 return Singleton<DllRedirector>::get();
58 }
59
60 bool DllRedirector::BuildSecurityAttributesForLock(
61 CSecurityAttributes* sec_attr) {
62 DCHECK(sec_attr);
63 if (base::win::GetVersion() < base::win::VERSION_VISTA) {
64 // Don't bother with changing ACLs on pre-vista.
65 return false;
66 }
67
68 bool success = false;
69
70 // Fill out the rest of the security descriptor from the process token.
71 CAccessToken token;
72 if (token.GetProcessToken(TOKEN_QUERY)) {
73 CSecurityDesc security_desc;
74 // Set the SACL from an SDDL string that allows access to low-integrity
75 // processes. See http://msdn.microsoft.com/en-us/library/bb625958.aspx.
76 if (security_desc.FromString(L"S:(ML;;NW;;;LW)")) {
77 CSid sid_owner;
78 if (token.GetOwner(&sid_owner)) {
79 security_desc.SetOwner(sid_owner);
80 } else {
81 NOTREACHED() << "Could not get owner.";
82 }
83 CSid sid_group;
84 if (token.GetPrimaryGroup(&sid_group)) {
85 security_desc.SetGroup(sid_group);
86 } else {
87 NOTREACHED() << "Could not get group.";
88 }
89 CDacl dacl;
90 if (token.GetDefaultDacl(&dacl)) {
91 // Add an access control entry mask for the current user.
92 // This is what grants this user access from lower integrity levels.
93 CSid sid_user;
94 if (token.GetUser(&sid_user)) {
95 success = dacl.AddAllowedAce(sid_user, MUTEX_ALL_ACCESS);
96 security_desc.SetDacl(dacl);
97 sec_attr->Set(security_desc);
98 }
99 }
100 }
101 }
102
103 return success;
104 }
105
106 bool DllRedirector::SetFileMappingToReadOnly(base::SharedMemoryHandle mapping) {
107 bool success = false;
108
109 CAccessToken token;
110 if (token.GetProcessToken(TOKEN_QUERY)) {
111 CSid sid_user;
112 if (token.GetUser(&sid_user)) {
113 CDacl dacl;
114 dacl.AddAllowedAce(sid_user, STANDARD_RIGHTS_READ | FILE_MAP_READ);
115 success = AtlSetDacl(mapping, SE_KERNEL_OBJECT, dacl);
116 }
117 }
118
119 return success;
120 }
121
122
123 bool DllRedirector::RegisterAsFirstCFModule() {
124 DCHECK(first_module_handle_ == NULL);
125
126 // Build our own file version outside of the lock:
127 scoped_ptr<Version> our_version(GetCurrentModuleVersion());
128
129 // We sadly can't use the autolock here since we want to have a timeout.
130 // Be careful not to return while holding the lock. Also, attempt to do as
131 // little as possible while under this lock.
132
133 bool lock_acquired = false;
134 CSecurityAttributes sec_attr;
135 if (base::win::GetVersion() >= base::win::VERSION_VISTA &&
136 BuildSecurityAttributesForLock(&sec_attr)) {
137 // On vista and above, we need to explicitly allow low integrity access
138 // to our objects. On XP, we don't bother.
139 lock_acquired = shared_memory_->Lock(kSharedMemoryLockTimeoutMs, &sec_attr);
140 } else {
141 lock_acquired = shared_memory_->Lock(kSharedMemoryLockTimeoutMs, NULL);
142 }
143
144 if (!lock_acquired) {
145 // We couldn't get the lock in a reasonable amount of time, so fall
146 // back to loading our current version. We return true to indicate that the
147 // caller should not attempt to delegate to an already loaded version.
148 dll_version_.swap(our_version);
149 return true;
150 }
151
152 bool created_beacon = true;
153 bool result = shared_memory_->CreateNamed(shared_memory_name_.c_str(),
154 false, // open_existing
155 kSharedMemorySize);
156
157 if (result) {
158 // We created the beacon, now we need to mutate the security attributes
159 // on the shared memory to allow read-only access and let low-integrity
160 // processes open it. This will fail on FAT32 file systems.
161 if (!SetFileMappingToReadOnly(shared_memory_->handle())) {
162 DLOG(ERROR) << "Failed to set file mapping permissions.";
163 }
164 } else {
165 created_beacon = false;
166
167 // We failed to create the shared memory segment, suggesting it may already
168 // exist: try to create it read-only.
169 result = shared_memory_->Open(shared_memory_name_.c_str(),
170 true /* read_only */);
171 }
172
173 if (result) {
174 // Map in the whole thing.
175 result = shared_memory_->Map(0);
176 DCHECK(shared_memory_->memory());
177
178 if (result) {
179 // Either write our own version number or read it in if it was already
180 // present in the shared memory section.
181 if (created_beacon) {
182 dll_version_.swap(our_version);
183
184 lstrcpynA(reinterpret_cast<char*>(shared_memory_->memory()),
185 dll_version_->GetString().c_str(),
186 std::min(kSharedMemorySize,
187 dll_version_->GetString().length() + 1));
188 } else {
189 char buffer[kSharedMemorySize] = {0};
190 memcpy(buffer, shared_memory_->memory(), kSharedMemorySize - 1);
191 dll_version_.reset(new Version(buffer));
192
193 if (!dll_version_->IsValid() ||
194 dll_version_->Equals(*our_version.get())) {
195 // If we either couldn't parse a valid version out of the shared
196 // memory or we did parse a version and it is the same as our own,
197 // then pretend we're first in to avoid trying to load any other DLLs.
198 dll_version_.reset(our_version.release());
199 created_beacon = true;
200 }
201 }
202 } else {
203 NOTREACHED() << "Failed to map in version beacon.";
204 }
205 } else {
206 NOTREACHED() << "Could not create file mapping for version beacon, gle: "
207 << ::GetLastError();
208 }
209
210 // Matching Unlock.
211 shared_memory_->Unlock();
212
213 return created_beacon;
214 }
215
216 void DllRedirector::UnregisterAsFirstCFModule() {
217 if (base::SharedMemory::IsHandleValid(shared_memory_->handle())) {
218 bool lock_acquired = shared_memory_->Lock(kSharedMemoryLockTimeoutMs, NULL);
219 if (lock_acquired) {
220 // Free our handles. The last closed handle SHOULD result in it being
221 // deleted.
222 shared_memory_->Close();
223 shared_memory_->Unlock();
224 }
225 }
226 }
227
228 LPFNGETCLASSOBJECT DllRedirector::GetDllGetClassObjectPtr() {
229 HMODULE first_module_handle = GetFirstModule();
230
231 LPFNGETCLASSOBJECT proc_ptr = NULL;
232 if (first_module_handle) {
233 proc_ptr = reinterpret_cast<LPFNGETCLASSOBJECT>(
234 GetProcAddress(first_module_handle, "DllGetClassObject"));
235 DPLOG_IF(ERROR, !proc_ptr) << "DllRedirector: Could not get address of "
236 "DllGetClassObject from first loaded module.";
237 }
238
239 return proc_ptr;
240 }
241
242 Version* DllRedirector::GetCurrentModuleVersion() {
243 scoped_ptr<FileVersionInfo> file_version_info(
244 FileVersionInfo::CreateFileVersionInfoForCurrentModule());
245 DCHECK(file_version_info.get());
246
247 scoped_ptr<Version> current_version;
248 if (file_version_info.get()) {
249 current_version.reset(
250 new Version(WideToASCII(file_version_info->file_version())));
251 DCHECK(current_version->IsValid());
252 }
253
254 return current_version.release();
255 }
256
257 HMODULE DllRedirector::GetFirstModule() {
258 DCHECK(dll_version_.get())
259 << "Error: Did you call RegisterAsFirstCFModule() first?";
260
261 if (first_module_handle_ == NULL) {
262 first_module_handle_ = LoadVersionedModule(dll_version_.get());
263 }
264
265 if (first_module_handle_ == reinterpret_cast<HMODULE>(&__ImageBase)) {
266 NOTREACHED() << "Should not be loading own version.";
267 first_module_handle_ = NULL;
268 }
269
270 return first_module_handle_;
271 }
272
273 HMODULE DllRedirector::LoadVersionedModule(Version* version) {
274 DCHECK(version);
275
276 HMODULE hmodule = NULL;
277 wchar_t system_buffer[MAX_PATH];
278 HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase);
279 system_buffer[0] = 0;
280 if (GetModuleFileName(this_module, system_buffer,
281 arraysize(system_buffer)) != 0) {
282 base::FilePath module_path(system_buffer);
283
284 // For a module located in
285 // Foo\XXXXXXXXX\<module>.dll, load
286 // Foo\<version>\<module>.dll:
287 base::FilePath module_name = module_path.BaseName();
288 module_path = module_path.DirName()
289 .DirName()
290 .Append(base::ASCIIToWide(version->GetString()))
291 .Append(module_name);
292
293 hmodule = LoadLibrary(module_path.value().c_str());
294 if (hmodule == NULL) {
295 DPLOG(ERROR) << "Could not load reported module version "
296 << version->GetString();
297 }
298 } else {
299 DPLOG(FATAL) << "Failed to get module file name";
300 }
301 return hmodule;
302 }
OLDNEW
« no previous file with comments | « chrome_frame/dll_redirector.h ('k') | chrome_frame/event_hooker.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698