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

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
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>
11 11
12 #include "base/at_exit.h" 12 #include "base/at_exit.h"
13 #include "base/command_line.h" 13 #include "base/command_line.h"
14 #include "base/file_util.h" 14 #include "base/file_util.h"
15 #include "base/file_version_info.h" 15 #include "base/file_version_info.h"
16 #include "base/logging.h" 16 #include "base/logging.h"
17 #include "base/logging_win.h" 17 #include "base/logging_win.h"
18 #include "base/memory/scoped_vector.h"
18 #include "base/path_service.h" 19 #include "base/path_service.h"
19 #include "base/string_number_conversions.h" 20 #include "base/string_number_conversions.h"
20 #include "base/string_piece.h" 21 #include "base/string_piece.h"
21 #include "base/string_util.h" 22 #include "base/string_util.h"
22 #include "base/sys_string_conversions.h" 23 #include "base/sys_string_conversions.h"
23 #include "base/win/registry.h" 24 #include "base/win/registry.h"
24 #include "base/win/windows_version.h" 25 #include "base/win/windows_version.h"
25 #include "chrome/common/chrome_constants.h" 26 #include "chrome/common/chrome_constants.h"
26 #include "chrome/common/chrome_switches.h" 27 #include "chrome/common/chrome_switches.h"
27 #include "chrome/installer/util/google_update_settings.h" 28 #include "chrome/installer/util/google_update_settings.h"
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 return hr; 185 return hr;
185 } 186 }
186 187
187 // See comments in AddCommonRGSReplacements 188 // See comments in AddCommonRGSReplacements
188 bool do_system_registration_; 189 bool do_system_registration_;
189 }; 190 };
190 191
191 ChromeTabModule _AtlModule; 192 ChromeTabModule _AtlModule;
192 193
193 base::AtExitManager* g_exit_manager = NULL; 194 base::AtExitManager* g_exit_manager = NULL;
194 bool RegisterSecuredMimeHandler(bool enable, bool is_system); // forward 195 HRESULT RegisterSecuredMimeHandler(bool enable, bool is_system); // forward
195 196
196 // DLL Entry Point 197 // DLL Entry Point
197 extern "C" BOOL WINAPI DllMain(HINSTANCE instance, 198 extern "C" BOOL WINAPI DllMain(HINSTANCE instance,
198 DWORD reason, 199 DWORD reason,
199 LPVOID reserved) { 200 LPVOID reserved) {
200 UNREFERENCED_PARAMETER(instance); 201 UNREFERENCED_PARAMETER(instance);
201 if (reason == DLL_PROCESS_ATTACH) { 202 if (reason == DLL_PROCESS_ATTACH) {
202 #ifndef NDEBUG 203 #ifndef NDEBUG
203 // Silence traces from the ATL registrar to reduce the log noise. 204 // Silence traces from the ATL registrar to reduce the log noise.
204 ATL::CTrace::s_trace.ChangeCategory(atlTraceRegistrar, 0, 205 ATL::CTrace::s_trace.ChangeCategory(atlTraceRegistrar, 0,
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 // needs doing. 342 // needs doing.
342 result = S_FALSE; 343 result = S_FALSE;
343 } 344 }
344 345
345 return result; 346 return result;
346 } 347 }
347 348
348 // Helper method called for user-level installs where we don't have admin 349 // 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 350 // permissions. Starts up the long running process and registers it to get it
350 // started at next boot. 351 // started at next boot.
351 void SetupUserLevelHelper() { 352 HRESULT SetupUserLevelHelper() {
353 HRESULT hr = S_OK;
354
352 // Remove existing run-at-startup entry. 355 // Remove existing run-at-startup entry.
353 base::win::RemoveCommandFromAutoRun(HKEY_CURRENT_USER, kRunKeyName); 356 base::win::RemoveCommandFromAutoRun(HKEY_CURRENT_USER, kRunKeyName);
354 357
355 // Build the chrome_frame_helper command line. 358 // Build the chrome_frame_helper command line.
356 FilePath module_path; 359 FilePath module_path;
357 FilePath helper_path; 360 FilePath helper_path;
358 if (PathService::Get(base::FILE_MODULE, &module_path)) { 361 if (PathService::Get(base::FILE_MODULE, &module_path)) {
359 module_path = module_path.DirName(); 362 module_path = module_path.DirName();
360 helper_path = module_path.Append(kChromeFrameHelperExe); 363 helper_path = module_path.Append(kChromeFrameHelperExe);
361 if (!file_util::PathExists(helper_path)) { 364 if (!file_util::PathExists(helper_path)) {
362 // If we can't find the helper in the current directory, try looking 365 // 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). 366 // one up (this is the layout in the build output folder).
364 module_path = module_path.DirName(); 367 module_path = module_path.DirName();
365 helper_path = module_path.Append(kChromeFrameHelperExe); 368 helper_path = module_path.Append(kChromeFrameHelperExe);
366 DCHECK(file_util::PathExists(helper_path)) << 369 DCHECK(file_util::PathExists(helper_path)) <<
367 "Could not find chrome_frame_helper.exe."; 370 "Could not find chrome_frame_helper.exe.";
368 } 371 }
372
373 // Find window handle of existing instance.
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,
grt (UTC plus 2) 2011/09/06 14:56:55 if this fails, installation will continue but GCF
robertshield 2011/09/06 20:23:42 Nope, we now fail on this as well.
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 hr = E_FAIL;
grt (UTC plus 2) 2011/09/06 14:56:55 this will now cause installation to fail and rollb
robertshield 2011/09/06 20:23:42 Yes, this is desired. New IE instances will not re
393 NOTREACHED();
394 LOG(ERROR) << "Could not launch helper process.";
grt (UTC plus 2) 2011/09/06 14:56:55 Do you think the last-error code might be useful h
robertshield 2011/09/06 20:23:42 So changed, although sadly this won't show up in t
grt (UTC plus 2) 2011/09/07 15:00:48 frown. so the logging stuff in DllMain is a noop
robertshield 2011/09/07 17:58:11 As far as I can tell, this is the case. It may be
395 }
396
397 // Kill old instance using window handle.
398 if (IsWindow(old_window)) {
399 BOOL result = PostMessage(old_window, WM_CLOSE, 0, 0);
400 if (!result) {
401 LOG(ERROR) << "Failed to post close message to old helper process: "
grt (UTC plus 2) 2011/09/06 14:56:55 PLOG and remove GetLastError
robertshield 2011/09/06 20:23:42 Done.
402 << GetLastError();
403 }
404 }
405 } else {
406 hr = ERROR_FILE_NOT_FOUND;
grt (UTC plus 2) 2011/09/06 14:56:55 hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
robertshield 2011/09/06 20:23:42 Done.
407 }
369 } else { 408 } else {
409 hr = E_UNEXPECTED;
370 NOTREACHED(); 410 NOTREACHED();
371 } 411 }
372 412
373 // Find window handle of existing instance. 413 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 } 414 }
406 415
407 416
408 // Used to determine whether the DLL can be unloaded by OLE 417 // Used to determine whether the DLL can be unloaded by OLE
409 STDAPI DllCanUnloadNow() { 418 STDAPI DllCanUnloadNow() {
410 return _AtlModule.DllCanUnloadNow(); 419 return _AtlModule.DllCanUnloadNow();
411 } 420 }
412 421
413 // Returns a class factory to create an object of the requested type 422 // Returns a class factory to create an object of the requested type
414 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) { 423 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) {
(...skipping 18 matching lines...) Expand all
433 const wchar_t kChromeFramePrefix[] = L"chromeframe/"; 442 const wchar_t kChromeFramePrefix[] = L"chromeframe/";
434 443
435 // To delete the user agent, set value to NULL. 444 // To delete the user agent, set value to NULL.
436 // The is_system parameter indicates whether this is a per machine or a per 445 // The is_system parameter indicates whether this is a per machine or a per
437 // user installation. 446 // user installation.
438 HRESULT SetChromeFrameUA(bool is_system, const wchar_t* value) { 447 HRESULT SetChromeFrameUA(bool is_system, const wchar_t* value) {
439 HRESULT hr = E_FAIL; 448 HRESULT hr = E_FAIL;
440 HKEY parent_hive = is_system ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 449 HKEY parent_hive = is_system ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
441 450
442 RegKey ua_key; 451 RegKey ua_key;
443 if (ua_key.Create(parent_hive, kPostPlatformUAKey, 452 if (ua_key.Create(parent_hive, kPostPlatformUAKey,
grt (UTC plus 2) 2011/09/06 14:56:55 capture the return value here
robertshield 2011/09/06 20:23:42 Done.
444 KEY_READ | KEY_WRITE) == ERROR_SUCCESS) { 453 KEY_READ | KEY_WRITE) == ERROR_SUCCESS) {
445 // Make sure that we unregister ChromeFrame UA strings registered previously 454 // Make sure that we unregister ChromeFrame UA strings registered previously
446 wchar_t value_name[MAX_PATH + 1] = {}; 455 wchar_t value_name[MAX_PATH + 1] = {};
447 wchar_t value_data[MAX_PATH + 1] = {}; 456 wchar_t value_data[MAX_PATH + 1] = {};
448 457
449 DWORD value_index = 0; 458 DWORD value_index = 0;
450 while (value_index < ua_key.ValueCount()) { 459 while (value_index < ua_key.ValueCount()) {
451 DWORD name_size = arraysize(value_name); 460 DWORD name_size = arraysize(value_name);
452 DWORD value_size = arraysize(value_data); 461 DWORD value_size = arraysize(value_data);
453 DWORD type = 0; 462 DWORD type = 0;
(...skipping 12 matching lines...) Expand all
466 } 475 }
467 } 476 }
468 477
469 std::wstring chrome_frame_ua_value_name = kChromeFramePrefix; 478 std::wstring chrome_frame_ua_value_name = kChromeFramePrefix;
470 chrome_frame_ua_value_name += GetCurrentModuleVersion(); 479 chrome_frame_ua_value_name += GetCurrentModuleVersion();
471 if (value) { 480 if (value) {
472 ua_key.WriteValue(chrome_frame_ua_value_name.c_str(), value); 481 ua_key.WriteValue(chrome_frame_ua_value_name.c_str(), value);
473 } 482 }
474 hr = S_OK; 483 hr = S_OK;
475 } else { 484 } else {
476 DLOG(ERROR) << __FUNCTION__ << ": " << kPostPlatformUAKey; 485 DLOG(ERROR) << __FUNCTION__ << ": " << kPostPlatformUAKey;
grt (UTC plus 2) 2011/09/06 14:56:55 log the captured return value here
robertshield 2011/09/06 20:23:42 Done.
477 hr = E_UNEXPECTED; 486 hr = E_UNEXPECTED;
grt (UTC plus 2) 2011/09/06 14:56:55 hr = HRESULT_FROM_WIN32(captured value)
robertshield 2011/09/06 20:23:42 Done.
478 } 487 }
479 return hr; 488 return hr;
480 } 489 }
481 490
grt (UTC plus 2) 2011/09/06 14:56:55 consider adding a comment indicating that what fol
robertshield 2011/09/06 20:23:42 Done.
491 HRESULT RegisterActiveDoc(bool reg, bool is_system) {
492 // We have to call the static T::UpdateRegistry function instead of
493 // _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_ACTIVEDOC, reg)
494 // because there is specific OLEMISC replacement.
495 return ChromeActiveDocument::UpdateRegistry(reg);
496 }
497
498 HRESULT RegisterActiveX(bool reg, bool is_system) {
499 // We have to call the static T::UpdateRegistry function instead of
500 // _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_ACTIVEX, reg)
501 // because there is specific OLEMISC replacement.
502 return ChromeFrameActivex::UpdateRegistry(reg);
503 }
504
505 HRESULT RegisterElevationPolicy(bool reg, bool is_system) {
506 if (reg && base::win::GetVersion() >= base::win::VERSION_VISTA) {
507 // Register the elevation policy. We do this only for developer
508 // convenience as the installer is really responsible for doing this.
grt (UTC plus 2) 2011/09/06 14:56:55 This comment says that the installer is responsibl
robertshield 2011/09/06 20:23:42 It does, in fact, do it. See install_worker.cc, Ad
509 // Because of that, we do not unregister this policy and just leave that
510 // up to the installer. Also we do not gate registration on this
511 // succeeding.
512 _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_ELEVATION,
513 reg);
514 RefreshElevationPolicy();
515 }
516 return S_OK;
517 }
518
519 HRESULT RegisterProtocol(bool reg, bool is_system) {
520 return _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEPROTOCOL, reg);
521 }
522
523 HRESULT RegisterBhoClsid(bool reg, bool is_system) {
524 return Bho::UpdateRegistry(reg);
525 }
526
527 HRESULT RegisterBhoIE(bool reg, bool is_system) {
528 if (is_system) {
529 return _AtlModule.UpdateRegistryFromResourceS(IDR_REGISTER_BHO, reg);
530 } else {
531 if (reg) {
532 // Setup the long running process:
533 return SetupUserLevelHelper();
534 } else {
535 // Unschedule the user-level helper. Note that we don't kill it here
536 // so that during updates we don't have a time window with no running
537 // helper. Uninstalls and updates will explicitly kill the helper from
538 // within the installer. Unregister existing run-at-startup entry.
539 return base::win::RemoveCommandFromAutoRun(HKEY_CURRENT_USER,
grt (UTC plus 2) 2011/09/06 14:56:55 return base::win::Remove...(...) ? S_OK : E_FAIL;
robertshield 2011/09/06 20:23:42 Done.
540 kRunKeyName);
541 }
542 }
543 }
544
545 HRESULT RegisterTypeLib(bool reg, bool is_system) {
546 if (reg && !is_system) {
547 // Enables the RegisterTypeLib Function function to override default
548 // registry mappings under Windows Vista Service Pack 1 (SP1),
549 // Windows Server 2008, and later operating system versions
550 typedef void (WINAPI* OaEnablePerUserTypeLibReg)(void);
551 OaEnablePerUserTypeLibReg per_user_typelib_func =
552 reinterpret_cast<OaEnablePerUserTypeLibReg>(
553 GetProcAddress(GetModuleHandle(L"oleaut32.dll"),
554 "OaEnablePerUserTLibRegistration"));
555 if (per_user_typelib_func) {
556 (*per_user_typelib_func)();
557 }
558 }
559 return reg ?
560 UtilRegisterTypeLib(_AtlComModule.m_hInstTypeLib,
561 NULL, !is_system) :
562 UtilUnRegisterTypeLib(_AtlComModule.m_hInstTypeLib,
563 NULL, !is_system);
564 }
565
566 HRESULT RegisterLegacyNPAPICleanup(bool reg, bool is_system) {
567 if (!reg) {
568 _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_NPAPI, reg);
569 UtilRemovePersistentNPAPIMarker();
570 }
571 // Ignore failures.
572 return S_OK;
573 }
574
grt (UTC plus 2) 2011/09/06 14:56:55 remove extra newline
robertshield 2011/09/06 20:23:42 Done.
575
576 HRESULT RegisterAppId(bool reg, bool is_system) {
577 return _AtlModule.UpdateRegistryAppId(reg);
578 }
579
grt (UTC plus 2) 2011/09/06 14:56:55 remove extra newline
robertshield 2011/09/06 20:23:42 Done.
580
581 HRESULT RegisterUserAgent(bool reg, bool is_system) {
582 if (reg) {
583 return SetChromeFrameUA(is_system, L"1");
584 } else {
585 return SetChromeFrameUA(is_system, NULL);
586 }
587 }
588
589 enum RegistrationSteps {
grt (UTC plus 2) 2011/09/06 14:56:55 nit: make this singular since an instance of the t
robertshield 2011/09/06 20:23:42 Done.
590 kStepSecuredMimeHandler = 0,
591 kStepActiveDoc = 1,
592 kStepActiveX = 2,
593 kStepElevationPolicy = 3,
594 kStepProtocol = 4,
595 kStepBhoClsid = 5,
596 kStepBhoRegistration = 6,
597 kStepRegisterTypeLib = 7,
598 kStepNpapiCleanup = 8,
599 kStepAppId = 9,
600 kStepUserAgent = 10,
601 kStepEnd = 11
602 };
603
482 enum RegistrationFlags { 604 enum RegistrationFlags {
483 ACTIVEX = 0x0001, 605 ACTIVEX = 0x0001,
484 ACTIVEDOC = 0x0002, 606 ACTIVEDOC = 0x0002,
485 GCF_PROTOCOL = 0x0004, 607 GCF_PROTOCOL = 0x0004,
486 BHO_CLSID = 0x0008, 608 BHO_CLSID = 0x0008,
487 BHO_REGISTRATION = 0x0010, 609 BHO_REGISTRATION = 0x0010,
488 TYPELIB = 0x0020, 610 TYPELIB = 0x0020,
489 611
490 ALL = 0xFFFF 612 ALL = 0xFFFF
491 }; 613 };
492 614
493 STDAPI CustomRegistration(UINT reg_flags, BOOL reg, bool is_system) { 615 // Mux the failure step into the hresult. We take only the first four bits
494 UINT flags = reg_flags; 616 // and stick those into the top four bits of the facility code. We also set the
617 // Customer bit to be polite. Graphically, we write our error code to the
618 // bits marked with ^:
619 // | 1 2 3 |
620 // |0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1|
621 // |S|R|C|N|X|Facility |Code |
622 // ^ ^ ^ ^ ^
623 // See http://msdn.microsoft.com/en-us/library/cc231198(PROT.10).aspx for
624 // more details on HRESULTS.
625 //
626 // The resulting error can be extracted by:
627 // error_code = (fiddled_hr & 0x07800000) >> 23
628 HRESULT MuxErrorIntoHRESULT(HRESULT hr, int error_code) {
629 DCHECK_GE(error_code, 0);
630 DCHECK_LT(error_code, kStepEnd);
631 COMPILE_ASSERT(kStepEnd <= 0xF, update_error_muxing_too_many_steps);
495 632
496 if (reg && (flags & (ACTIVEDOC | ACTIVEX))) 633 // Check that our four desired bits are clear.
497 flags |= (TYPELIB | GCF_PROTOCOL); 634 // 0xF87FFFFF == 11111000011111111111111111111111
635 DCHECK_EQ(static_cast<HRESULT>(hr & 0xF87FFFFF), hr);
498 636
499 HRESULT hr = S_OK; 637 HRESULT fiddled_hr = ((error_code & 0xF) << 23) | hr;
638 fiddled_hr |= 1 << 29; // Set the customer bit.
639
640 return fiddled_hr;
641 }
642
643 HRESULT CustomRegistration(uint16 reg_flags, bool reg, bool is_system) {
644 if (reg && (reg_flags & (ACTIVEDOC | ACTIVEX)))
645 reg_flags |= (TYPELIB | GCF_PROTOCOL);
500 646
501 // Set the flag that gets checked in AddCommonRGSReplacements before doing 647 // Set the flag that gets checked in AddCommonRGSReplacements before doing
502 // registration work. 648 // registration work.
503 _AtlModule.do_system_registration_ = is_system; 649 _AtlModule.do_system_registration_ = is_system;
504 650
505 if ((hr == S_OK) && (flags & ACTIVEDOC)) { 651 typedef HRESULT (*RegistrationFn)(bool reg, bool is_system);
506 // Don't fail to unregister if we can't undo the secure mime 652 struct RegistrationStep {
507 // handler registration. This was observed getting hit during 653 int id;
grt (UTC plus 2) 2011/09/06 14:56:55 how about RegistrationStepId rather than int? thi
robertshield 2011/09/06 20:23:42 Done.
508 // uninstallation. 654 uint32 condition;
grt (UTC plus 2) 2011/09/06 14:56:55 since reg_flags is a uint16, should this be, too?
robertshield 2011/09/06 20:23:42 Done.
509 if (!RegisterSecuredMimeHandler(reg ? true : false, is_system) && reg) 655 RegistrationFn func;
510 return E_FAIL; 656 };
511 hr = ChromeActiveDocument::UpdateRegistry(reg); 657 static const RegistrationStep registration_steps[] = {
512 } 658 { kStepSecuredMimeHandler, ACTIVEDOC, &RegisterSecuredMimeHandler },
659 { kStepActiveDoc, ACTIVEDOC, &RegisterActiveDoc },
660 { kStepActiveX, ACTIVEX, &RegisterActiveX },
661 { kStepElevationPolicy, (ACTIVEDOC | ACTIVEX), &RegisterElevationPolicy },
662 { kStepProtocol, GCF_PROTOCOL, &RegisterProtocol },
663 { kStepBhoClsid, BHO_CLSID, &RegisterBhoClsid },
664 { kStepBhoRegistration, BHO_REGISTRATION, &RegisterBhoIE },
665 { kStepRegisterTypeLib, TYPELIB, &RegisterTypeLib },
666 { kStepNpapiCleanup, ALL, &RegisterLegacyNPAPICleanup },
667 { kStepAppId, ALL, &RegisterAppId },
668 { kStepUserAgent, ALL, &RegisterUserAgent }
669 };
513 670
514 if ((hr == S_OK) && (flags & ACTIVEX)) { 671 HRESULT hr = S_OK;
515 // We have to call the static T::UpdateRegistry function instead of 672 bool rollback = false;
516 // _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_ACTIVEX, reg) 673 int failure_step = 0;
517 // because there is specific OLEMISC replacement. 674 for (int step = 0; step < arraysize(registration_steps); ++step) {
518 hr = ChromeFrameActivex::UpdateRegistry(reg); 675 if ((reg_flags & registration_steps[step].condition) != 0) {
519 } 676 hr = registration_steps[step].func(reg, is_system);
520 677 if (FAILED(hr) && reg) {
521 // Register the elevation policy. We do this only for developer convenience 678 rollback = true;
522 // as the installer is really responsible for doing this. 679 failure_step = step;
523 // Because of that, we do not unregister this policy and just leave that up 680 break;
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 } 681 }
552 } 682 }
553 } 683 }
554 684
555 if ((hr == S_OK) && (flags & TYPELIB)) { 685 if (rollback) {
556 if (reg && !is_system) { 686 DCHECK(reg);
557 // Enables the RegisterTypeLib Function function to override default 687 // Rollback the failing action and all preceding ones.
558 // registry mappings under Windows Vista Service Pack 1 (SP1), 688 for (int rollback_step = failure_step;
grt (UTC plus 2) 2011/09/06 14:56:55 how about reusing "step" so this doesn't need so m
robertshield 2011/09/06 20:23:42 Done.
559 // Windows Server 2008, and later operating system versions 689 rollback_step >= 0;
560 typedef void (WINAPI* OaEnablePerUserTypeLibReg)(void); 690 --rollback_step) {
561 OaEnablePerUserTypeLibReg per_user_typelib_func = 691 registration_steps[rollback_step].func(!reg, is_system);
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 } 692 }
569 hr = (reg)?
570 UtilRegisterTypeLib(_AtlComModule.m_hInstTypeLib, NULL, !is_system) :
571 UtilUnRegisterTypeLib(_AtlComModule.m_hInstTypeLib, NULL, !is_system);
572 } 693 }
573 694
574 // Unconditionally remove NPAPI registration when unregistering any component. 695 return MuxErrorIntoHRESULT(hr, failure_step);
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 } 696 }
594 697
595
596
597 // DllRegisterServer - Adds entries to the system registry 698 // DllRegisterServer - Adds entries to the system registry
598 STDAPI DllRegisterServer() { 699 STDAPI DllRegisterServer() {
599 UINT flags = ACTIVEX | ACTIVEDOC | TYPELIB | GCF_PROTOCOL | 700 uint16 flags = ACTIVEX | ACTIVEDOC | TYPELIB | GCF_PROTOCOL |
600 BHO_CLSID | BHO_REGISTRATION; 701 BHO_CLSID | BHO_REGISTRATION;
601 702
602 HRESULT hr = CustomRegistration(flags, TRUE, true); 703 HRESULT hr = CustomRegistration(flags, true, true);
603 if (SUCCEEDED(hr)) { 704 if (SUCCEEDED(hr)) {
604 SetupRunOnce(); 705 SetupRunOnce();
605 } 706 }
606 707
607 return hr; 708 return hr;
608 } 709 }
609 710
610 // DllUnregisterServer - Removes entries from the system registry 711 // DllUnregisterServer - Removes entries from the system registry
611 STDAPI DllUnregisterServer() { 712 STDAPI DllUnregisterServer() {
612 HRESULT hr = CustomRegistration(ALL, FALSE, true); 713 HRESULT hr = CustomRegistration(ALL, false, true);
613 return hr; 714 return hr;
614 } 715 }
615 716
616 // DllRegisterServer - Adds entries to the HKCU hive in the registry 717 // DllRegisterUserServer - Adds entries to the HKCU hive in the registry.
617 STDAPI DllRegisterUserServer() { 718 STDAPI DllRegisterUserServer() {
618 UINT flags = ACTIVEX | ACTIVEDOC | TYPELIB | GCF_PROTOCOL | 719 UINT flags = ACTIVEX | ACTIVEDOC | TYPELIB | GCF_PROTOCOL |
619 BHO_CLSID | BHO_REGISTRATION; 720 BHO_CLSID | BHO_REGISTRATION;
620 721
621 HRESULT hr = CustomRegistration(flags, TRUE, false); 722 HRESULT hr = CustomRegistration(flags, TRUE, false);
622 if (SUCCEEDED(hr)) { 723 if (SUCCEEDED(hr)) {
623 SetupRunOnce(); 724 SetupRunOnce();
624 } 725 }
625 726
626 return hr; 727 return hr;
627 } 728 }
628 729
629 // DllRegisterServer - Removes entries from the HKCU hive in the registry. 730 // DllUnregisterUserServer - Removes entries from the HKCU hive in the registry.
630 STDAPI DllUnregisterUserServer() { 731 STDAPI DllUnregisterUserServer() {
631 HRESULT hr = CustomRegistration(ALL, FALSE, false); 732 HRESULT hr = CustomRegistration(ALL, FALSE, false);
632 return hr; 733 return hr;
633 } 734 }
634 735
635 class SecurityDescBackup { 736 class SecurityDescBackup {
636 public: 737 public:
637 explicit SecurityDescBackup(const std::wstring& backup_key) 738 explicit SecurityDescBackup(const std::wstring& backup_key)
638 : backup_key_name_(backup_key) {} 739 : backup_key_name_(backup_key) {}
639 ~SecurityDescBackup() {} 740 ~SecurityDescBackup() {}
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
739 return user_; 840 return user_;
740 } 841 }
741 842
742 private: 843 private:
743 CAccessToken token_; 844 CAccessToken token_;
744 CTokenPrivileges take_ownership_; 845 CTokenPrivileges take_ownership_;
745 CTokenPrivileges restore_; 846 CTokenPrivileges restore_;
746 CSid user_; 847 CSid user_;
747 }; 848 };
748 849
749 static bool SetOrDeleteMimeHandlerKey(bool set, HKEY root_key) { 850 static HRESULT SetOrDeleteMimeHandlerKey(bool set, HKEY root_key) {
grt (UTC plus 2) 2011/09/06 14:56:55 nit: move this (and the above classes) into the un
robertshield 2011/09/06 20:23:42 Done.
750 std::wstring key_name = kInternetSettings; 851 std::wstring key_name = kInternetSettings;
751 key_name.append(L"\\Secure Mime Handlers"); 852 key_name.append(L"\\Secure Mime Handlers");
752 RegKey key(root_key, key_name.c_str(), KEY_READ | KEY_WRITE); 853 RegKey key(root_key, key_name.c_str(), KEY_READ | KEY_WRITE);
753 if (!key.Valid()) 854 if (!key.Valid())
754 return false; 855 return false;
755 856
756 LONG result1 = ERROR_SUCCESS; 857 LONG result1 = ERROR_SUCCESS;
757 LONG result2 = ERROR_SUCCESS; 858 LONG result2 = ERROR_SUCCESS;
758 if (set) { 859 if (set) {
759 result1 = key.WriteValue(L"ChromeTab.ChromeActiveDocument", 1); 860 result1 = key.WriteValue(L"ChromeTab.ChromeActiveDocument", 1);
760 result2 = key.WriteValue(L"ChromeTab.ChromeActiveDocument.1", 1); 861 result2 = key.WriteValue(L"ChromeTab.ChromeActiveDocument.1", 1);
761 } else { 862 } else {
762 result1 = key.DeleteValue(L"ChromeTab.ChromeActiveDocument"); 863 result1 = key.DeleteValue(L"ChromeTab.ChromeActiveDocument");
763 result2 = key.DeleteValue(L"ChromeTab.ChromeActiveDocument.1"); 864 result2 = key.DeleteValue(L"ChromeTab.ChromeActiveDocument.1");
764 } 865 }
765 866
766 return (result2 == ERROR_SUCCESS) && (result2 == ERROR_SUCCESS); 867 return result1 != ERROR_SUCCESS ? HRESULT_FROM_WIN32(result1) :
868 HRESULT_FROM_WIN32(result2);
767 } 869 }
768 870
769 bool RegisterSecuredMimeHandler(bool enable, bool is_system) { 871 HRESULT RegisterSecuredMimeHandler(bool enable, bool is_system) {
grt (UTC plus 2) 2011/09/06 14:56:55 nit: move this so that it lives with the other reg
robertshield 2011/09/06 20:23:42 Done.
770 if (!is_system) { 872 if (!is_system) {
771 return SetOrDeleteMimeHandlerKey(enable, HKEY_CURRENT_USER); 873 return SetOrDeleteMimeHandlerKey(enable, HKEY_CURRENT_USER);
772 } else if (base::win::GetVersion() < base::win::VERSION_VISTA) { 874 } else if (base::win::GetVersion() < base::win::VERSION_VISTA) {
773 return SetOrDeleteMimeHandlerKey(enable, HKEY_LOCAL_MACHINE); 875 return SetOrDeleteMimeHandlerKey(enable, HKEY_LOCAL_MACHINE);
774 } 876 }
775 877
776 std::wstring mime_key = kInternetSettings; 878 std::wstring mime_key = kInternetSettings;
777 mime_key.append(L"\\Secure Mime Handlers"); 879 mime_key.append(L"\\Secure Mime Handlers");
778 std::wstring backup_key = kInternetSettings; 880 std::wstring backup_key = kInternetSettings;
779 backup_key.append(L"\\__backup_SMH__"); 881 backup_key.append(L"\\__backup_SMH__");
780 std::wstring object_name = L"MACHINE\\"; 882 std::wstring object_name = L"MACHINE\\";
781 object_name.append(mime_key); 883 object_name.append(mime_key);
782 884
783 TokenWithPrivileges token_; 885 TokenWithPrivileges token_;
784 if (!token_.EnablePrivileges()) 886 if (!token_.EnablePrivileges())
785 return false; 887 return E_ACCESSDENIED;
786 888
787 // If there is a backup key - something bad happened; try to restore 889 // If there is a backup key - something bad happened; try to restore
788 // security on "Secure Mime Handlers" from the backup. 890 // security on "Secure Mime Handlers" from the backup.
789 SecurityDescBackup backup(backup_key); 891 SecurityDescBackup backup(backup_key);
790 backup.RestoreSecurity(object_name.c_str()); 892 backup.RestoreSecurity(object_name.c_str());
791 893
792 // Read old security descriptor of the Mime key first. 894 // Read old security descriptor of the Mime key first.
793 CSecurityDesc sd; 895 CSecurityDesc sd;
794 if (!AtlGetSecurityDescriptor(object_name.c_str(), SE_REGISTRY_KEY, &sd)) { 896 if (!AtlGetSecurityDescriptor(object_name.c_str(), SE_REGISTRY_KEY, &sd)) {
795 return false; 897 return E_FAIL;
796 } 898 }
797 899
798 backup.SaveSecurity(sd); 900 backup.SaveSecurity(sd);
799 bool result = false; 901 HRESULT hr = E_FAIL;
800 // set new owner 902 // set new owner
801 if (AtlSetOwnerSid(object_name.c_str(), SE_REGISTRY_KEY, token_.GetUser())) { 903 if (AtlSetOwnerSid(object_name.c_str(), SE_REGISTRY_KEY, token_.GetUser())) {
802 // set new dacl 904 // set new dacl
803 CDacl new_dacl; 905 CDacl new_dacl;
804 sd.GetDacl(&new_dacl); 906 sd.GetDacl(&new_dacl);
805 new_dacl.AddAllowedAce(token_.GetUser(), GENERIC_WRITE | GENERIC_READ); 907 new_dacl.AddAllowedAce(token_.GetUser(), GENERIC_WRITE | GENERIC_READ);
806 if (AtlSetDacl(object_name.c_str(), SE_REGISTRY_KEY, new_dacl)) { 908 if (AtlSetDacl(object_name.c_str(), SE_REGISTRY_KEY, new_dacl)) {
807 result = SetOrDeleteMimeHandlerKey(enable, HKEY_LOCAL_MACHINE); 909 hr = SetOrDeleteMimeHandlerKey(enable, HKEY_LOCAL_MACHINE);
808 } 910 }
809 } 911 }
810 912
811 backup.RestoreSecurity(object_name.c_str()); 913 backup.RestoreSecurity(object_name.c_str());
812 return result; 914 return hr;
813 } 915 }
OLDNEW
« chrome/installer/util/self_reg_work_item.cc ('K') | « 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