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

Side by Side Diff: chrome_frame/chrome_tab.cc

Issue 7824010: Make Chrome Frame registration and unregistration more robust. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 3 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/installer/util/self_reg_work_item.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // chrome_tab.cc : Implementation of DLL Exports. 5 // chrome_tab.cc : Implementation of DLL Exports.
6 6
7 // Include without path to make GYP build see it. 7 // Include without path to make GYP build see it.
8 #include "chrome_tab.h" // NOLINT 8 #include "chrome_tab.h" // NOLINT
9 9
10 #include <atlsecurity.h> 10 #include <atlsecurity.h>
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 // This function has the side effect of initializing an unprotected 45 // This function has the side effect of initializing an unprotected
46 // vector pointer inside GoogleUrl. If this is called during DLL loading, 46 // vector pointer inside GoogleUrl. If this is called during DLL loading,
47 // it has the effect of avoiding an initialization race on that pointer. 47 // it has the effect of avoiding an initialization race on that pointer.
48 // TODO(siggi): fix GoogleUrl. 48 // TODO(siggi): fix GoogleUrl.
49 void InitGoogleUrl() { 49 void InitGoogleUrl() {
50 static const char kDummyUrl[] = "http://www.google.com"; 50 static const char kDummyUrl[] = "http://www.google.com";
51 51
52 url_util::IsStandard(kDummyUrl, 52 url_util::IsStandard(kDummyUrl,
53 url_parse::MakeRange(0, arraysize(kDummyUrl))); 53 url_parse::MakeRange(0, arraysize(kDummyUrl)));
54 } 54 }
55 }
56
57 static const wchar_t kBhoRegistryPath[] =
58 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"
59 L"\\Browser Helper Objects";
60 55
61 const wchar_t kInternetSettings[] = 56 const wchar_t kInternetSettings[] =
62 L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"; 57 L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings";
63 58
64 const wchar_t kProtocolHandlers[] = 59 const wchar_t kProtocolHandlers[] =
65 L"Software\\Classes\\Protocols\\Handler"; 60 L"Software\\Classes\\Protocols\\Handler";
66 61
67 const wchar_t kRunOnce[] = 62 const wchar_t kRunOnce[] =
68 L"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce"; 63 L"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce";
69 64
70 const wchar_t kRunKeyName[] = L"ChromeFrameHelper"; 65 const wchar_t kRunKeyName[] = L"ChromeFrameHelper";
71 66
72 const wchar_t kChromeFrameHelperExe[] = L"chrome_frame_helper.exe"; 67 const wchar_t kChromeFrameHelperExe[] = L"chrome_frame_helper.exe";
73 const wchar_t kChromeFrameHelperStartupArg[] = L"--startup"; 68 const wchar_t kChromeFrameHelperStartupArg[] = L"--startup";
74 69
75 // Window class and window names. 70 // Window class and window names.
76 // TODO(robertshield): These and other constants need to be refactored into 71 // TODO(robertshield): These and other constants need to be refactored into
77 // a common chrome_frame_constants.h|cc and built into a separate lib 72 // a common chrome_frame_constants.h|cc and built into a separate lib
78 // (either chrome_frame_utils or make another one). 73 // (either chrome_frame_utils or make another one).
79 const wchar_t kChromeFrameHelperWindowClassName[] = 74 const wchar_t kChromeFrameHelperWindowClassName[] =
80 L"ChromeFrameHelperWindowClass"; 75 L"ChromeFrameHelperWindowClass";
81 const wchar_t kChromeFrameHelperWindowName[] = 76 const wchar_t kChromeFrameHelperWindowName[] =
82 L"ChromeFrameHelperWindowName"; 77 L"ChromeFrameHelperWindowName";
83 78
84 // {0562BFC3-2550-45b4-BD8E-A310583D3A6F} 79 // {0562BFC3-2550-45b4-BD8E-A310583D3A6F}
85 static const GUID kChromeFrameProvider = 80 static const GUID kChromeFrameProvider =
86 { 0x562bfc3, 0x2550, 0x45b4, 81 { 0x562bfc3, 0x2550, 0x45b4,
87 { 0xbd, 0x8e, 0xa3, 0x10, 0x58, 0x3d, 0x3a, 0x6f } }; 82 { 0xbd, 0x8e, 0xa3, 0x10, 0x58, 0x3d, 0x3a, 0x6f } };
88 83
89 // Object entries go here instead of with each object, so that we can move 84 const wchar_t kPostPlatformUAKey[] =
90 // the objects to a lib. Also reduces magic. 85 L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\"
91 OBJECT_ENTRY_AUTO(CLSID_ChromeFrameBHO, Bho) 86 L"User Agent\\Post Platform";
92 OBJECT_ENTRY_AUTO(__uuidof(ChromeActiveDocument), ChromeActiveDocument) 87 const wchar_t kChromeFramePrefix[] = L"chromeframe/";
93 OBJECT_ENTRY_AUTO(__uuidof(ChromeFrame), ChromeFrameActivex)
94 OBJECT_ENTRY_AUTO(__uuidof(ChromeProtocol), ChromeProtocol)
95
96 88
97 // See comments in DllGetClassObject. 89 // See comments in DllGetClassObject.
98 LPFNGETCLASSOBJECT g_dll_get_class_object_redir_ptr = NULL; 90 LPFNGETCLASSOBJECT g_dll_get_class_object_redir_ptr = NULL;
99 91
100 class ChromeTabModule : public CAtlDllModuleT<ChromeTabModule> { 92 class ChromeTabModule : public CAtlDllModuleT<ChromeTabModule> {
101 public: 93 public:
102 typedef CAtlDllModuleT<ChromeTabModule> ParentClass; 94 typedef CAtlDllModuleT<ChromeTabModule> ParentClass;
103 95
104 ChromeTabModule() : do_system_registration_(true) {} 96 ChromeTabModule() : do_system_registration_(true) {}
105 97
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 return hr; 176 return hr;
185 } 177 }
186 178
187 // See comments in AddCommonRGSReplacements 179 // See comments in AddCommonRGSReplacements
188 bool do_system_registration_; 180 bool do_system_registration_;
189 }; 181 };
190 182
191 ChromeTabModule _AtlModule; 183 ChromeTabModule _AtlModule;
192 184
193 base::AtExitManager* g_exit_manager = NULL; 185 base::AtExitManager* g_exit_manager = NULL;
194 bool RegisterSecuredMimeHandler(bool enable, bool is_system); // forward
195 186
196 // DLL Entry Point
197 extern "C" BOOL WINAPI DllMain(HINSTANCE instance,
198 DWORD reason,
199 LPVOID reserved) {
200 UNREFERENCED_PARAMETER(instance);
201 if (reason == DLL_PROCESS_ATTACH) {
202 #ifndef NDEBUG
203 // Silence traces from the ATL registrar to reduce the log noise.
204 ATL::CTrace::s_trace.ChangeCategory(atlTraceRegistrar, 0,
205 ATLTRACESTATUS_DISABLED);
206 #endif
207 InitGoogleUrl();
208
209 g_exit_manager = new base::AtExitManager();
210 CommandLine::Init(0, NULL);
211 InitializeCrashReporting();
212 logging::InitLogging(
213 NULL,
214 logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
215 logging::LOCK_LOG_FILE,
216 logging::DELETE_OLD_LOG_FILE,
217 logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS);
218
219 DllRedirector* dll_redirector = DllRedirector::GetInstance();
220 DCHECK(dll_redirector);
221
222 if (!dll_redirector->RegisterAsFirstCFModule()) {
223 // Someone else was here first, try and get a pointer to their
224 // DllGetClassObject export:
225 g_dll_get_class_object_redir_ptr =
226 dll_redirector->GetDllGetClassObjectPtr();
227 DCHECK(g_dll_get_class_object_redir_ptr != NULL)
228 << "Found CF module with no DllGetClassObject export.";
229 }
230
231 // Enable ETW logging.
232 logging::LogEventProvider::Initialize(kChromeFrameProvider);
233 } else if (reason == DLL_PROCESS_DETACH) {
234 DllRedirector* dll_redirector = DllRedirector::GetInstance();
235 DCHECK(dll_redirector);
236
237 dll_redirector->UnregisterAsFirstCFModule();
238 g_patch_helper.UnpatchIfNeeded();
239 delete g_exit_manager;
240 g_exit_manager = NULL;
241 ShutdownCrashReporting();
242 }
243 return _AtlModule.DllMain(reason, reserved);
244 }
245
246 #ifdef _MANAGED
247 #pragma managed(pop)
248 #endif
249 187
250 HRESULT RefreshElevationPolicy() { 188 HRESULT RefreshElevationPolicy() {
251 const wchar_t kIEFrameDll[] = L"ieframe.dll"; 189 const wchar_t kIEFrameDll[] = L"ieframe.dll";
252 const char kIERefreshPolicy[] = "IERefreshElevationPolicy"; 190 const char kIERefreshPolicy[] = "IERefreshElevationPolicy";
253 HRESULT hr = E_NOTIMPL; 191 HRESULT hr = E_NOTIMPL;
254 192
255 // Stick an SEH in the chain to prevent the VEH from picking up on first 193 // Stick an SEH in the chain to prevent the VEH from picking up on first
256 // chance exceptions caused by loading ieframe.dll. Use the vanilla 194 // chance exceptions caused by loading ieframe.dll. Use the vanilla
257 // ExceptionBarrier to report any exceptions that do make their way to us 195 // ExceptionBarrier to report any exceptions that do make their way to us
258 // though. 196 // though.
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 // needs doing. 279 // needs doing.
342 result = S_FALSE; 280 result = S_FALSE;
343 } 281 }
344 282
345 return result; 283 return result;
346 } 284 }
347 285
348 // Helper method called for user-level installs where we don't have admin 286 // Helper method called for user-level installs where we don't have admin
349 // permissions. Starts up the long running process and registers it to get it 287 // permissions. Starts up the long running process and registers it to get it
350 // started at next boot. 288 // started at next boot.
351 void SetupUserLevelHelper() { 289 HRESULT SetupUserLevelHelper() {
290 HRESULT hr = S_OK;
291
352 // Remove existing run-at-startup entry. 292 // Remove existing run-at-startup entry.
353 base::win::RemoveCommandFromAutoRun(HKEY_CURRENT_USER, kRunKeyName); 293 base::win::RemoveCommandFromAutoRun(HKEY_CURRENT_USER, kRunKeyName);
354 294
355 // Build the chrome_frame_helper command line. 295 // Build the chrome_frame_helper command line.
356 FilePath module_path; 296 FilePath module_path;
357 FilePath helper_path; 297 FilePath helper_path;
358 if (PathService::Get(base::FILE_MODULE, &module_path)) { 298 if (PathService::Get(base::FILE_MODULE, &module_path)) {
359 module_path = module_path.DirName(); 299 module_path = module_path.DirName();
360 helper_path = module_path.Append(kChromeFrameHelperExe); 300 helper_path = module_path.Append(kChromeFrameHelperExe);
361 if (!file_util::PathExists(helper_path)) { 301 if (!file_util::PathExists(helper_path)) {
362 // If we can't find the helper in the current directory, try looking 302 // If we can't find the helper in the current directory, try looking
363 // one up (this is the layout in the build output folder). 303 // one up (this is the layout in the build output folder).
364 module_path = module_path.DirName(); 304 module_path = module_path.DirName();
365 helper_path = module_path.Append(kChromeFrameHelperExe); 305 helper_path = module_path.Append(kChromeFrameHelperExe);
366 DCHECK(file_util::PathExists(helper_path)) << 306 DCHECK(file_util::PathExists(helper_path)) <<
367 "Could not find chrome_frame_helper.exe."; 307 "Could not find chrome_frame_helper.exe.";
368 } 308 }
309
310 // Find window handle of existing instance.
311 HWND old_window = FindWindow(kChromeFrameHelperWindowClassName,
312 kChromeFrameHelperWindowName);
313
314 if (file_util::PathExists(helper_path)) {
315 std::wstring helper_path_cmd(L"\"");
316 helper_path_cmd += helper_path.value();
317 helper_path_cmd += L"\" ";
318 helper_path_cmd += kChromeFrameHelperStartupArg;
319
320 // Add new run-at-startup entry.
321 if (!base::win::AddCommandToAutoRun(HKEY_CURRENT_USER, kRunKeyName,
322 helper_path_cmd)) {
323 hr = E_FAIL;
324 LOG(ERROR) << "Could not add helper process to auto run key.";
325 }
326
327 // Start new instance.
328 base::LaunchOptions options;
329 options.start_hidden = true;
330 bool launched = base::LaunchProcess(helper_path.value(), options, NULL);
331 if (!launched) {
332 hr = E_FAIL;
333 PLOG(DFATAL) << "Could not launch helper process.";
334 }
335
336 // Kill old instance using window handle.
337 if (IsWindow(old_window)) {
338 BOOL result = PostMessage(old_window, WM_CLOSE, 0, 0);
339 if (!result) {
340 PLOG(ERROR) << "Failed to post close message to old helper process: ";
341 }
342 }
343 } else {
344 hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
345 }
369 } else { 346 } else {
347 hr = E_UNEXPECTED;
370 NOTREACHED(); 348 NOTREACHED();
371 } 349 }
372 350
373 // Find window handle of existing instance. 351 return hr;
374 HWND old_window = FindWindow(kChromeFrameHelperWindowClassName,
375 kChromeFrameHelperWindowName);
376
377 if (file_util::PathExists(helper_path)) {
378 std::wstring helper_path_cmd(L"\"");
379 helper_path_cmd += helper_path.value();
380 helper_path_cmd += L"\" ";
381 helper_path_cmd += kChromeFrameHelperStartupArg;
382
383 // Add new run-at-startup entry.
384 base::win::AddCommandToAutoRun(HKEY_CURRENT_USER, kRunKeyName,
385 helper_path_cmd);
386
387 // Start new instance.
388 base::LaunchOptions options;
389 options.start_hidden = true;
390 bool launched = base::LaunchProcess(helper_path.value(), options, NULL);
391 if (!launched) {
392 NOTREACHED();
393 LOG(ERROR) << "Could not launch helper process.";
394 }
395
396 // Kill old instance using window handle.
397 if (IsWindow(old_window)) {
398 BOOL result = PostMessage(old_window, WM_CLOSE, 0, 0);
399 if (!result) {
400 LOG(ERROR) << "Failed to post close message to old helper process: "
401 << GetLastError();
402 }
403 }
404 }
405 } 352 }
406 353
407
408 // Used to determine whether the DLL can be unloaded by OLE
409 STDAPI DllCanUnloadNow() {
410 return _AtlModule.DllCanUnloadNow();
411 }
412
413 // Returns a class factory to create an object of the requested type
414 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) {
415 // If we found another module present when we were loaded, then delegate to
416 // that:
417 if (g_dll_get_class_object_redir_ptr) {
418 return g_dll_get_class_object_redir_ptr(rclsid, riid, ppv);
419 }
420
421 // Enable sniffing and switching only if asked for BHO
422 // (we use BHO to get loaded in IE).
423 if (rclsid == CLSID_ChromeFrameBHO) {
424 g_patch_helper.InitializeAndPatchProtocolsIfNeeded();
425 }
426
427 return _AtlModule.DllGetClassObject(rclsid, riid, ppv);
428 }
429
430 const wchar_t kPostPlatformUAKey[] =
431 L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\"
432 L"User Agent\\Post Platform";
433 const wchar_t kChromeFramePrefix[] = L"chromeframe/";
434
435 // To delete the user agent, set value to NULL. 354 // To delete the user agent, set value to NULL.
436 // The is_system parameter indicates whether this is a per machine or a per 355 // The is_system parameter indicates whether this is a per machine or a per
437 // user installation. 356 // user installation.
438 HRESULT SetChromeFrameUA(bool is_system, const wchar_t* value) { 357 HRESULT SetChromeFrameUA(bool is_system, const wchar_t* value) {
439 HRESULT hr = E_FAIL; 358 HRESULT hr = E_FAIL;
440 HKEY parent_hive = is_system ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 359 HKEY parent_hive = is_system ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
441 360
442 RegKey ua_key; 361 RegKey ua_key;
443 if (ua_key.Create(parent_hive, kPostPlatformUAKey, 362 LONG reg_result = ua_key.Create(parent_hive, kPostPlatformUAKey,
444 KEY_READ | KEY_WRITE) == ERROR_SUCCESS) { 363 KEY_READ | KEY_WRITE);
364 if (reg_result == ERROR_SUCCESS) {
445 // Make sure that we unregister ChromeFrame UA strings registered previously 365 // Make sure that we unregister ChromeFrame UA strings registered previously
446 wchar_t value_name[MAX_PATH + 1] = {}; 366 wchar_t value_name[MAX_PATH + 1] = {};
447 wchar_t value_data[MAX_PATH + 1] = {}; 367 wchar_t value_data[MAX_PATH + 1] = {};
448 368
449 DWORD value_index = 0; 369 DWORD value_index = 0;
450 while (value_index < ua_key.ValueCount()) { 370 while (value_index < ua_key.ValueCount()) {
451 DWORD name_size = arraysize(value_name); 371 DWORD name_size = arraysize(value_name);
452 DWORD value_size = arraysize(value_data); 372 DWORD value_size = arraysize(value_data);
453 DWORD type = 0; 373 DWORD type = 0;
454 LRESULT ret = ::RegEnumValue(ua_key.Handle(), value_index, value_name, 374 LRESULT ret = ::RegEnumValue(ua_key.Handle(), value_index, value_name,
(...skipping 11 matching lines...) Expand all
466 } 386 }
467 } 387 }
468 388
469 std::wstring chrome_frame_ua_value_name = kChromeFramePrefix; 389 std::wstring chrome_frame_ua_value_name = kChromeFramePrefix;
470 chrome_frame_ua_value_name += GetCurrentModuleVersion(); 390 chrome_frame_ua_value_name += GetCurrentModuleVersion();
471 if (value) { 391 if (value) {
472 ua_key.WriteValue(chrome_frame_ua_value_name.c_str(), value); 392 ua_key.WriteValue(chrome_frame_ua_value_name.c_str(), value);
473 } 393 }
474 hr = S_OK; 394 hr = S_OK;
475 } else { 395 } else {
476 DLOG(ERROR) << __FUNCTION__ << ": " << kPostPlatformUAKey; 396 DLOG(ERROR) << __FUNCTION__ << ": " << kPostPlatformUAKey
477 hr = E_UNEXPECTED; 397 << ", error code = " << reg_result;
398 hr = HRESULT_FROM_WIN32(reg_result);
478 } 399 }
479 return hr; 400 return hr;
480 } 401 }
481 402
482 enum RegistrationFlags {
483 ACTIVEX = 0x0001,
484 ACTIVEDOC = 0x0002,
485 GCF_PROTOCOL = 0x0004,
486 BHO_CLSID = 0x0008,
487 BHO_REGISTRATION = 0x0010,
488 TYPELIB = 0x0020,
489
490 ALL = 0xFFFF
491 };
492
493 STDAPI CustomRegistration(UINT reg_flags, BOOL reg, bool is_system) {
494 UINT flags = reg_flags;
495
496 if (reg && (flags & (ACTIVEDOC | ACTIVEX)))
497 flags |= (TYPELIB | GCF_PROTOCOL);
498
499 HRESULT hr = S_OK;
500
501 // Set the flag that gets checked in AddCommonRGSReplacements before doing
502 // registration work.
503 _AtlModule.do_system_registration_ = is_system;
504
505 if ((hr == S_OK) && (flags & ACTIVEDOC)) {
506 // Don't fail to unregister if we can't undo the secure mime
507 // handler registration. This was observed getting hit during
508 // uninstallation.
509 if (!RegisterSecuredMimeHandler(reg ? true : false, is_system) && reg)
510 return E_FAIL;
511 hr = ChromeActiveDocument::UpdateRegistry(reg);
512 }
513
514 if ((hr == S_OK) && (flags & ACTIVEX)) {
515 // We have to call the static T::UpdateRegistry function instead of
516 // _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_ACTIVEX, reg)
517 // because there is specific OLEMISC replacement.
518 hr = ChromeFrameActivex::UpdateRegistry(reg);
519 }
520
521 // Register the elevation policy. We do this only for developer convenience
522 // as the installer is really responsible for doing this.
523 // Because of that, we do not unregister this policy and just leave that up
524 // to the installer.
525 if (hr == S_OK && (flags & (ACTIVEDOC | ACTIVEX)) && reg) {
526 _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_ELEVATION, reg);
527 RefreshElevationPolicy();
528 }
529
530 if ((hr == S_OK) && (flags & GCF_PROTOCOL)) {
531 hr = _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEPROTOCOL, reg);
532 }
533
534 if ((hr == S_OK) && (flags & BHO_CLSID)) {
535 hr = Bho::UpdateRegistry(reg);
536 }
537
538 if ((hr == S_OK) && (flags & BHO_REGISTRATION)) {
539 if (is_system) {
540 _AtlModule.UpdateRegistryFromResourceS(IDR_REGISTER_BHO, reg);
541 } else {
542 if (reg) {
543 // Setup the long running process:
544 SetupUserLevelHelper();
545 } else {
546 // Unschedule the user-level helper. Note that we don't kill it here so
547 // that during updates we don't have a time window with no running
548 // helper. Uninstalls and updates will explicitly kill the helper from
549 // within the installer. Unregister existing run-at-startup entry.
550 base::win::RemoveCommandFromAutoRun(HKEY_CURRENT_USER, kRunKeyName);
551 }
552 }
553 }
554
555 if ((hr == S_OK) && (flags & TYPELIB)) {
556 if (reg && !is_system) {
557 // Enables the RegisterTypeLib Function function to override default
558 // registry mappings under Windows Vista Service Pack 1 (SP1),
559 // Windows Server 2008, and later operating system versions
560 typedef void (WINAPI* OaEnablePerUserTypeLibReg)(void);
561 OaEnablePerUserTypeLibReg per_user_typelib_func =
562 reinterpret_cast<OaEnablePerUserTypeLibReg>(
563 GetProcAddress(GetModuleHandle(L"oleaut32.dll"),
564 "OaEnablePerUserTLibRegistration"));
565 if (per_user_typelib_func) {
566 (*per_user_typelib_func)();
567 }
568 }
569 hr = (reg)?
570 UtilRegisterTypeLib(_AtlComModule.m_hInstTypeLib, NULL, !is_system) :
571 UtilUnRegisterTypeLib(_AtlComModule.m_hInstTypeLib, NULL, !is_system);
572 }
573
574 // Unconditionally remove NPAPI registration when unregistering any component.
575 if ((hr == S_OK) && !reg) {
576 // Ignore failures.
577 _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_NPAPI, reg);
578 UtilRemovePersistentNPAPIMarker();
579 }
580
581 if (hr == S_OK) {
582 hr = _AtlModule.UpdateRegistryAppId(reg);
583 }
584
585 if (hr == S_OK) {
586 if (reg) {
587 hr = SetChromeFrameUA(is_system, L"1");
588 } else {
589 hr = SetChromeFrameUA(is_system, NULL);
590 }
591 }
592 return hr;
593 }
594
595
596
597 // DllRegisterServer - Adds entries to the system registry
598 STDAPI DllRegisterServer() {
599 UINT flags = ACTIVEX | ACTIVEDOC | TYPELIB | GCF_PROTOCOL |
600 BHO_CLSID | BHO_REGISTRATION;
601
602 HRESULT hr = CustomRegistration(flags, TRUE, true);
603 if (SUCCEEDED(hr)) {
604 SetupRunOnce();
605 }
606
607 return hr;
608 }
609
610 // DllUnregisterServer - Removes entries from the system registry
611 STDAPI DllUnregisterServer() {
612 HRESULT hr = CustomRegistration(ALL, FALSE, true);
613 return hr;
614 }
615
616 // DllRegisterServer - Adds entries to the HKCU hive in the registry
617 STDAPI DllRegisterUserServer() {
618 UINT flags = ACTIVEX | ACTIVEDOC | TYPELIB | GCF_PROTOCOL |
619 BHO_CLSID | BHO_REGISTRATION;
620
621 HRESULT hr = CustomRegistration(flags, TRUE, false);
622 if (SUCCEEDED(hr)) {
623 SetupRunOnce();
624 }
625
626 return hr;
627 }
628
629 // DllRegisterServer - Removes entries from the HKCU hive in the registry.
630 STDAPI DllUnregisterUserServer() {
631 HRESULT hr = CustomRegistration(ALL, FALSE, false);
632 return hr;
633 }
634
635 class SecurityDescBackup { 403 class SecurityDescBackup {
636 public: 404 public:
637 explicit SecurityDescBackup(const std::wstring& backup_key) 405 explicit SecurityDescBackup(const std::wstring& backup_key)
638 : backup_key_name_(backup_key) {} 406 : backup_key_name_(backup_key) {}
639 ~SecurityDescBackup() {} 407 ~SecurityDescBackup() {}
640 408
641 // Save given security descriptor to the backup key. 409 // Save given security descriptor to the backup key.
642 bool SaveSecurity(const CSecurityDesc& sd) { 410 bool SaveSecurity(const CSecurityDesc& sd) {
643 CString str; 411 CString str;
644 if (!sd.ToString(&str)) 412 if (!sd.ToString(&str))
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
739 return user_; 507 return user_;
740 } 508 }
741 509
742 private: 510 private:
743 CAccessToken token_; 511 CAccessToken token_;
744 CTokenPrivileges take_ownership_; 512 CTokenPrivileges take_ownership_;
745 CTokenPrivileges restore_; 513 CTokenPrivileges restore_;
746 CSid user_; 514 CSid user_;
747 }; 515 };
748 516
749 static bool SetOrDeleteMimeHandlerKey(bool set, HKEY root_key) { 517 HRESULT SetOrDeleteMimeHandlerKey(bool set, HKEY root_key) {
750 std::wstring key_name = kInternetSettings; 518 std::wstring key_name = kInternetSettings;
751 key_name.append(L"\\Secure Mime Handlers"); 519 key_name.append(L"\\Secure Mime Handlers");
752 RegKey key(root_key, key_name.c_str(), KEY_READ | KEY_WRITE); 520 RegKey key(root_key, key_name.c_str(), KEY_READ | KEY_WRITE);
753 if (!key.Valid()) 521 if (!key.Valid())
754 return false; 522 return false;
755 523
756 LONG result1 = ERROR_SUCCESS; 524 LONG result1 = ERROR_SUCCESS;
757 LONG result2 = ERROR_SUCCESS; 525 LONG result2 = ERROR_SUCCESS;
758 if (set) { 526 if (set) {
759 result1 = key.WriteValue(L"ChromeTab.ChromeActiveDocument", 1); 527 result1 = key.WriteValue(L"ChromeTab.ChromeActiveDocument", 1);
760 result2 = key.WriteValue(L"ChromeTab.ChromeActiveDocument.1", 1); 528 result2 = key.WriteValue(L"ChromeTab.ChromeActiveDocument.1", 1);
761 } else { 529 } else {
762 result1 = key.DeleteValue(L"ChromeTab.ChromeActiveDocument"); 530 result1 = key.DeleteValue(L"ChromeTab.ChromeActiveDocument");
763 result2 = key.DeleteValue(L"ChromeTab.ChromeActiveDocument.1"); 531 result2 = key.DeleteValue(L"ChromeTab.ChromeActiveDocument.1");
764 } 532 }
765 533
766 return (result2 == ERROR_SUCCESS) && (result2 == ERROR_SUCCESS); 534 return result1 != ERROR_SUCCESS ? HRESULT_FROM_WIN32(result1) :
535 HRESULT_FROM_WIN32(result2);
767 } 536 }
768 537
769 bool RegisterSecuredMimeHandler(bool enable, bool is_system) { 538 // Chrome Frame registration functions.
539 //-----------------------------------------------------------------------------
540 HRESULT RegisterSecuredMimeHandler(bool enable, bool is_system) {
770 if (!is_system) { 541 if (!is_system) {
771 return SetOrDeleteMimeHandlerKey(enable, HKEY_CURRENT_USER); 542 return SetOrDeleteMimeHandlerKey(enable, HKEY_CURRENT_USER);
772 } else if (base::win::GetVersion() < base::win::VERSION_VISTA) { 543 } else if (base::win::GetVersion() < base::win::VERSION_VISTA) {
773 return SetOrDeleteMimeHandlerKey(enable, HKEY_LOCAL_MACHINE); 544 return SetOrDeleteMimeHandlerKey(enable, HKEY_LOCAL_MACHINE);
774 } 545 }
775 546
776 std::wstring mime_key = kInternetSettings; 547 std::wstring mime_key = kInternetSettings;
777 mime_key.append(L"\\Secure Mime Handlers"); 548 mime_key.append(L"\\Secure Mime Handlers");
778 std::wstring backup_key = kInternetSettings; 549 std::wstring backup_key = kInternetSettings;
779 backup_key.append(L"\\__backup_SMH__"); 550 backup_key.append(L"\\__backup_SMH__");
780 std::wstring object_name = L"MACHINE\\"; 551 std::wstring object_name = L"MACHINE\\";
781 object_name.append(mime_key); 552 object_name.append(mime_key);
782 553
783 TokenWithPrivileges token_; 554 TokenWithPrivileges token_;
784 if (!token_.EnablePrivileges()) 555 if (!token_.EnablePrivileges())
785 return false; 556 return E_ACCESSDENIED;
786 557
787 // If there is a backup key - something bad happened; try to restore 558 // If there is a backup key - something bad happened; try to restore
788 // security on "Secure Mime Handlers" from the backup. 559 // security on "Secure Mime Handlers" from the backup.
789 SecurityDescBackup backup(backup_key); 560 SecurityDescBackup backup(backup_key);
790 backup.RestoreSecurity(object_name.c_str()); 561 backup.RestoreSecurity(object_name.c_str());
791 562
792 // Read old security descriptor of the Mime key first. 563 // Read old security descriptor of the Mime key first.
793 CSecurityDesc sd; 564 CSecurityDesc sd;
794 if (!AtlGetSecurityDescriptor(object_name.c_str(), SE_REGISTRY_KEY, &sd)) { 565 if (!AtlGetSecurityDescriptor(object_name.c_str(), SE_REGISTRY_KEY, &sd)) {
795 return false; 566 return E_FAIL;
796 } 567 }
797 568
798 backup.SaveSecurity(sd); 569 backup.SaveSecurity(sd);
799 bool result = false; 570 HRESULT hr = E_FAIL;
800 // set new owner 571 // set new owner
801 if (AtlSetOwnerSid(object_name.c_str(), SE_REGISTRY_KEY, token_.GetUser())) { 572 if (AtlSetOwnerSid(object_name.c_str(), SE_REGISTRY_KEY, token_.GetUser())) {
802 // set new dacl 573 // set new dacl
803 CDacl new_dacl; 574 CDacl new_dacl;
804 sd.GetDacl(&new_dacl); 575 sd.GetDacl(&new_dacl);
805 new_dacl.AddAllowedAce(token_.GetUser(), GENERIC_WRITE | GENERIC_READ); 576 new_dacl.AddAllowedAce(token_.GetUser(), GENERIC_WRITE | GENERIC_READ);
806 if (AtlSetDacl(object_name.c_str(), SE_REGISTRY_KEY, new_dacl)) { 577 if (AtlSetDacl(object_name.c_str(), SE_REGISTRY_KEY, new_dacl)) {
807 result = SetOrDeleteMimeHandlerKey(enable, HKEY_LOCAL_MACHINE); 578 hr = SetOrDeleteMimeHandlerKey(enable, HKEY_LOCAL_MACHINE);
808 } 579 }
809 } 580 }
810 581
811 backup.RestoreSecurity(object_name.c_str()); 582 backup.RestoreSecurity(object_name.c_str());
812 return result; 583 return hr;
813 } 584 }
585
586 HRESULT RegisterActiveDoc(bool reg, bool is_system) {
587 // We have to call the static T::UpdateRegistry function instead of
588 // _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_ACTIVEDOC, reg)
589 // because there is specific OLEMISC replacement.
590 return ChromeActiveDocument::UpdateRegistry(reg);
591 }
592
593 HRESULT RegisterActiveX(bool reg, bool is_system) {
594 // We have to call the static T::UpdateRegistry function instead of
595 // _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_ACTIVEX, reg)
596 // because there is specific OLEMISC replacement.
597 return ChromeFrameActivex::UpdateRegistry(reg);
598 }
599
600 HRESULT RegisterElevationPolicy(bool reg, bool is_system) {
601 HRESULT hr = S_OK;
602 if (reg && base::win::GetVersion() >= base::win::VERSION_VISTA) {
603 // Register the elevation policy. This must succeed for Chrome Frame to
604 // be able launch Chrome when running in low-integrity IE.
605 hr = _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_ELEVATION,
606 reg);
607 if (SUCCEEDED(hr)) {
608 hr = RefreshElevationPolicy();
609 }
610 }
611 return hr;
612 }
613
614 HRESULT RegisterProtocol(bool reg, bool is_system) {
615 return _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEPROTOCOL, reg);
616 }
617
618 HRESULT RegisterBhoClsid(bool reg, bool is_system) {
619 return Bho::UpdateRegistry(reg);
620 }
621
622 HRESULT RegisterBhoIE(bool reg, bool is_system) {
623 if (is_system) {
624 return _AtlModule.UpdateRegistryFromResourceS(IDR_REGISTER_BHO, reg);
625 } else {
626 if (reg) {
627 // Setup the long running process:
628 return SetupUserLevelHelper();
629 } else {
630 // Unschedule the user-level helper. Note that we don't kill it here
631 // so that during updates we don't have a time window with no running
632 // helper. Uninstalls and updates will explicitly kill the helper from
633 // within the installer. Unregister existing run-at-startup entry.
634 return base::win::RemoveCommandFromAutoRun(HKEY_CURRENT_USER,
635 kRunKeyName) ? S_OK : E_FAIL;
636 }
637 }
638 }
639
640 HRESULT RegisterTypeLib(bool reg, bool is_system) {
641 if (reg && !is_system) {
642 // Enables the RegisterTypeLib Function function to override default
643 // registry mappings under Windows Vista Service Pack 1 (SP1),
644 // Windows Server 2008, and later operating system versions
645 typedef void (WINAPI* OaEnablePerUserTypeLibReg)(void);
646 OaEnablePerUserTypeLibReg per_user_typelib_func =
647 reinterpret_cast<OaEnablePerUserTypeLibReg>(
648 GetProcAddress(GetModuleHandle(L"oleaut32.dll"),
649 "OaEnablePerUserTLibRegistration"));
650 if (per_user_typelib_func) {
651 (*per_user_typelib_func)();
652 }
653 }
654 return reg ?
655 UtilRegisterTypeLib(_AtlComModule.m_hInstTypeLib,
656 NULL, !is_system) :
657 UtilUnRegisterTypeLib(_AtlComModule.m_hInstTypeLib,
658 NULL, !is_system);
659 }
660
661 HRESULT RegisterLegacyNPAPICleanup(bool reg, bool is_system) {
662 if (!reg) {
663 _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_NPAPI, reg);
664 UtilRemovePersistentNPAPIMarker();
665 }
666 // Ignore failures.
667 return S_OK;
668 }
669
670 HRESULT RegisterAppId(bool reg, bool is_system) {
671 return _AtlModule.UpdateRegistryAppId(reg);
672 }
673
674 HRESULT RegisterUserAgent(bool reg, bool is_system) {
675 if (reg) {
676 return SetChromeFrameUA(is_system, L"1");
677 } else {
678 return SetChromeFrameUA(is_system, NULL);
679 }
680 }
681
682 enum RegistrationStepId {
683 kStepSecuredMimeHandler = 0,
684 kStepActiveDoc = 1,
685 kStepActiveX = 2,
686 kStepElevationPolicy = 3,
687 kStepProtocol = 4,
688 kStepBhoClsid = 5,
689 kStepBhoRegistration = 6,
690 kStepRegisterTypeLib = 7,
691 kStepNpapiCleanup = 8,
692 kStepAppId = 9,
693 kStepUserAgent = 10,
694 kStepEnd = 11
695 };
696
697 enum RegistrationFlags {
698 ACTIVEX = 0x0001,
699 ACTIVEDOC = 0x0002,
700 GCF_PROTOCOL = 0x0004,
701 BHO_CLSID = 0x0008,
702 BHO_REGISTRATION = 0x0010,
703 TYPELIB = 0x0020,
704
705 ALL = 0xFFFF
706 };
707
708 // Mux the failure step into the hresult. We take only the first four bits
709 // and stick those into the top four bits of the facility code. We also set the
710 // Customer bit to be polite. Graphically, we write our error code to the
711 // bits marked with ^:
712 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
713 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
714 // +---+-+-+-----------------------+-------------------------------+
715 // |Sev|C|R| Facility | Code |
716 // +---+-+-+-----------------------+-------------------------------+
717 // ^ ^ ^ ^ ^
718 // See http://msdn.microsoft.com/en-us/library/cc231198(PROT.10).aspx for
719 // more details on HRESULTS.
720 //
721 // The resulting error can be extracted by:
722 // error_code = (fiddled_hr & 0x07800000) >> 23
723 HRESULT MuxErrorIntoHRESULT(HRESULT hr, int error_code) {
724 DCHECK_GE(error_code, 0);
725 DCHECK_LT(error_code, kStepEnd);
726 COMPILE_ASSERT(kStepEnd <= 0xF, update_error_muxing_too_many_steps);
727
728 // Check that our four desired bits are clear.
729 // 0xF87FFFFF == 11111000011111111111111111111111
730 DCHECK_EQ(static_cast<HRESULT>(hr & 0xF87FFFFF), hr);
731
732 HRESULT fiddled_hr = ((error_code & 0xF) << 23) | hr;
733 fiddled_hr |= 1 << 29; // Set the customer bit.
734
735 return fiddled_hr;
736 }
737
738 HRESULT CustomRegistration(uint16 reg_flags, bool reg, bool is_system) {
739 if (reg && (reg_flags & (ACTIVEDOC | ACTIVEX)))
740 reg_flags |= (TYPELIB | GCF_PROTOCOL);
741
742 // Set the flag that gets checked in AddCommonRGSReplacements before doing
743 // registration work.
744 _AtlModule.do_system_registration_ = is_system;
745
746 typedef HRESULT (*RegistrationFn)(bool reg, bool is_system);
747 struct RegistrationStep {
748 RegistrationStepId id;
749 uint16 condition;
750 RegistrationFn func;
751 };
752 static const RegistrationStep registration_steps[] = {
753 { kStepSecuredMimeHandler, ACTIVEDOC, &RegisterSecuredMimeHandler },
754 { kStepActiveDoc, ACTIVEDOC, &RegisterActiveDoc },
755 { kStepActiveX, ACTIVEX, &RegisterActiveX },
756 { kStepElevationPolicy, (ACTIVEDOC | ACTIVEX), &RegisterElevationPolicy },
757 { kStepProtocol, GCF_PROTOCOL, &RegisterProtocol },
758 { kStepBhoClsid, BHO_CLSID, &RegisterBhoClsid },
759 { kStepBhoRegistration, BHO_REGISTRATION, &RegisterBhoIE },
760 { kStepRegisterTypeLib, TYPELIB, &RegisterTypeLib },
761 { kStepNpapiCleanup, ALL, &RegisterLegacyNPAPICleanup },
762 { kStepAppId, ALL, &RegisterAppId },
763 { kStepUserAgent, ALL, &RegisterUserAgent }
764 };
765
766 HRESULT hr = S_OK;
767
768 bool rollback = false;
769 int failure_step = 0;
770 HRESULT step_hr = S_OK;
771 for (int step = 0; step < arraysize(registration_steps); ++step) {
772 if ((reg_flags & registration_steps[step].condition) != 0) {
773 step_hr = registration_steps[step].func(reg, is_system);
774 if (FAILED(step_hr)) {
775 // Store only the first failing HRESULT with the step value muxed in.
776 if (hr == S_OK) {
777 hr = MuxErrorIntoHRESULT(step_hr, step);
778 }
779
780 // On registration if a step fails, we abort and rollback.
781 if (reg) {
782 rollback = true;
783 failure_step = step;
784 break;
785 }
786 }
787 }
788 }
789
790 if (rollback) {
791 DCHECK(reg);
792 // Rollback the failing action and all preceding ones.
793 for (int step = failure_step; step >= 0; --step) {
794 registration_steps[step].func(!reg, is_system);
795 }
796 }
797
798 return hr;
799 }
800
801 } // namespace
802
803 // DLL Entry Point
804 extern "C" BOOL WINAPI DllMain(HINSTANCE instance,
805 DWORD reason,
806 LPVOID reserved) {
807 UNREFERENCED_PARAMETER(instance);
808 if (reason == DLL_PROCESS_ATTACH) {
809 #ifndef NDEBUG
810 // Silence traces from the ATL registrar to reduce the log noise.
811 ATL::CTrace::s_trace.ChangeCategory(atlTraceRegistrar, 0,
812 ATLTRACESTATUS_DISABLED);
813 #endif
814 InitGoogleUrl();
815
816 g_exit_manager = new base::AtExitManager();
817 CommandLine::Init(0, NULL);
818 InitializeCrashReporting();
819 logging::InitLogging(
820 NULL,
821 logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
822 logging::LOCK_LOG_FILE,
823 logging::DELETE_OLD_LOG_FILE,
824 logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS);
825
826 DllRedirector* dll_redirector = DllRedirector::GetInstance();
827 DCHECK(dll_redirector);
828
829 if (!dll_redirector->RegisterAsFirstCFModule()) {
830 // Someone else was here first, try and get a pointer to their
831 // DllGetClassObject export:
832 g_dll_get_class_object_redir_ptr =
833 dll_redirector->GetDllGetClassObjectPtr();
834 DCHECK(g_dll_get_class_object_redir_ptr != NULL)
835 << "Found CF module with no DllGetClassObject export.";
836 }
837
838 // Enable ETW logging.
839 logging::LogEventProvider::Initialize(kChromeFrameProvider);
840 } else if (reason == DLL_PROCESS_DETACH) {
841 DllRedirector* dll_redirector = DllRedirector::GetInstance();
842 DCHECK(dll_redirector);
843
844 dll_redirector->UnregisterAsFirstCFModule();
845 g_patch_helper.UnpatchIfNeeded();
846 delete g_exit_manager;
847 g_exit_manager = NULL;
848 ShutdownCrashReporting();
849 }
850 return _AtlModule.DllMain(reason, reserved);
851 }
852
853 // Used to determine whether the DLL can be unloaded by OLE
854 STDAPI DllCanUnloadNow() {
855 return _AtlModule.DllCanUnloadNow();
856 }
857
858 // Returns a class factory to create an object of the requested type
859 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) {
860 // If we found another module present when we were loaded, then delegate to
861 // that:
862 if (g_dll_get_class_object_redir_ptr) {
863 return g_dll_get_class_object_redir_ptr(rclsid, riid, ppv);
864 }
865
866 // Enable sniffing and switching only if asked for BHO
867 // (we use BHO to get loaded in IE).
868 if (rclsid == CLSID_ChromeFrameBHO) {
869 g_patch_helper.InitializeAndPatchProtocolsIfNeeded();
870 }
871
872 return _AtlModule.DllGetClassObject(rclsid, riid, ppv);
873 }
874
875 // DllRegisterServer - Adds entries to the system registry
876 STDAPI DllRegisterServer() {
877 uint16 flags = ACTIVEX | ACTIVEDOC | TYPELIB | GCF_PROTOCOL |
878 BHO_CLSID | BHO_REGISTRATION;
879
880 HRESULT hr = CustomRegistration(flags, true, true);
881 if (SUCCEEDED(hr)) {
882 SetupRunOnce();
883 }
884
885 return hr;
886 }
887
888 // DllUnregisterServer - Removes entries from the system registry
889 STDAPI DllUnregisterServer() {
890 HRESULT hr = CustomRegistration(ALL, false, true);
891 return hr;
892 }
893
894 // DllRegisterUserServer - Adds entries to the HKCU hive in the registry.
895 STDAPI DllRegisterUserServer() {
896 UINT flags = ACTIVEX | ACTIVEDOC | TYPELIB | GCF_PROTOCOL |
897 BHO_CLSID | BHO_REGISTRATION;
898
899 HRESULT hr = CustomRegistration(flags, TRUE, false);
900 if (SUCCEEDED(hr)) {
901 SetupRunOnce();
902 }
903
904 return hr;
905 }
906
907 // DllUnregisterUserServer - Removes entries from the HKCU hive in the registry.
908 STDAPI DllUnregisterUserServer() {
909 HRESULT hr = CustomRegistration(ALL, FALSE, false);
910 return hr;
911 }
912
913 // Object entries go here instead of with each object, so that we can move
914 // the objects to a lib. Also reduces magic.
915 OBJECT_ENTRY_AUTO(CLSID_ChromeFrameBHO, Bho)
916 OBJECT_ENTRY_AUTO(__uuidof(ChromeActiveDocument), ChromeActiveDocument)
917 OBJECT_ENTRY_AUTO(__uuidof(ChromeFrame), ChromeFrameActivex)
918 OBJECT_ENTRY_AUTO(__uuidof(ChromeProtocol), ChromeProtocol)
OLDNEW
« no previous file with comments | « chrome/installer/util/self_reg_work_item.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698