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

Side by Side Diff: chrome_frame/chrome_tab.cc

Issue 8055021: Merge 100224 - Make Chrome Frame registration and unregistration more robust and make it return e... (Closed) Base URL: svn://svn.chromium.org/chrome/branches/874/src/
Patch Set: Created 9 years, 2 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 // Note that this is not done on unregistration, the installer will
606 // explicitly remove the policy on uninstall.
607 hr = _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_ELEVATION,
608 reg);
609 if (SUCCEEDED(hr)) {
610 hr = RefreshElevationPolicy();
611 }
612 }
613 return hr;
614 }
615
616 HRESULT RegisterProtocol(bool reg, bool is_system) {
617 return _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEPROTOCOL, reg);
618 }
619
620 HRESULT RegisterBhoClsid(bool reg, bool is_system) {
621 return Bho::UpdateRegistry(reg);
622 }
623
624 HRESULT RegisterBhoIE(bool reg, bool is_system) {
625 if (is_system) {
626 return _AtlModule.UpdateRegistryFromResourceS(IDR_REGISTER_BHO, reg);
627 } else {
628 if (reg) {
629 // Setup the long running process:
630 return SetupUserLevelHelper();
631 } else {
632 // Unschedule the user-level helper. Note that we don't kill it here
633 // so that during updates we don't have a time window with no running
634 // helper. Uninstalls and updates will explicitly kill the helper from
635 // within the installer. Unregister existing run-at-startup entry.
636 return base::win::RemoveCommandFromAutoRun(HKEY_CURRENT_USER,
637 kRunKeyName) ? S_OK : E_FAIL;
638 }
639 }
640 }
641
642 HRESULT RegisterTypeLib(bool reg, bool is_system) {
643 if (reg && !is_system) {
644 // Enables the RegisterTypeLib Function function to override default
645 // registry mappings under Windows Vista Service Pack 1 (SP1),
646 // Windows Server 2008, and later operating system versions
647 typedef void (WINAPI* OaEnablePerUserTypeLibReg)(void);
648 OaEnablePerUserTypeLibReg per_user_typelib_func =
649 reinterpret_cast<OaEnablePerUserTypeLibReg>(
650 GetProcAddress(GetModuleHandle(L"oleaut32.dll"),
651 "OaEnablePerUserTLibRegistration"));
652 if (per_user_typelib_func) {
653 (*per_user_typelib_func)();
654 }
655 }
656 return reg ?
657 UtilRegisterTypeLib(_AtlComModule.m_hInstTypeLib,
658 NULL, !is_system) :
659 UtilUnRegisterTypeLib(_AtlComModule.m_hInstTypeLib,
660 NULL, !is_system);
661 }
662
663 HRESULT RegisterLegacyNPAPICleanup(bool reg, bool is_system) {
664 if (!reg) {
665 _AtlModule.UpdateRegistryFromResourceS(IDR_CHROMEFRAME_NPAPI, reg);
666 UtilRemovePersistentNPAPIMarker();
667 }
668 // Ignore failures.
669 return S_OK;
670 }
671
672 HRESULT RegisterAppId(bool reg, bool is_system) {
673 return _AtlModule.UpdateRegistryAppId(reg);
674 }
675
676 HRESULT RegisterUserAgent(bool reg, bool is_system) {
677 if (reg) {
678 return SetChromeFrameUA(is_system, L"1");
679 } else {
680 return SetChromeFrameUA(is_system, NULL);
681 }
682 }
683
684 enum RegistrationStepId {
685 kStepSecuredMimeHandler = 0,
686 kStepActiveDoc = 1,
687 kStepActiveX = 2,
688 kStepElevationPolicy = 3,
689 kStepProtocol = 4,
690 kStepBhoClsid = 5,
691 kStepBhoRegistration = 6,
692 kStepRegisterTypeLib = 7,
693 kStepNpapiCleanup = 8,
694 kStepAppId = 9,
695 kStepUserAgent = 10,
696 kStepEnd = 11
697 };
698
699 enum RegistrationFlags {
700 ACTIVEX = 0x0001,
701 ACTIVEDOC = 0x0002,
702 GCF_PROTOCOL = 0x0004,
703 BHO_CLSID = 0x0008,
704 BHO_REGISTRATION = 0x0010,
705 TYPELIB = 0x0020,
706
707 ALL = 0xFFFF
708 };
709
710 // Mux the failure step into the hresult. We take only the first four bits
711 // and stick those into the top four bits of the facility code. We also set the
712 // Customer bit to be polite. Graphically, we write our error code to the
713 // bits marked with ^:
714 // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
715 // 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
716 // +---+-+-+-----------------------+-------------------------------+
717 // |Sev|C|R| Facility | Code |
718 // +---+-+-+-----------------------+-------------------------------+
719 // ^ ^ ^ ^ ^
720 // See http://msdn.microsoft.com/en-us/library/cc231198(PROT.10).aspx for
721 // more details on HRESULTS.
722 //
723 // The resulting error can be extracted by:
724 // error_code = (fiddled_hr & 0x07800000) >> 23
725 HRESULT MuxErrorIntoHRESULT(HRESULT hr, int error_code) {
726 DCHECK_GE(error_code, 0);
727 DCHECK_LT(error_code, kStepEnd);
728 COMPILE_ASSERT(kStepEnd <= 0xF, update_error_muxing_too_many_steps);
729
730 // Check that our four desired bits are clear.
731 // 0xF87FFFFF == 11111000011111111111111111111111
732 DCHECK_EQ(static_cast<HRESULT>(hr & 0xF87FFFFF), hr);
733
734 HRESULT fiddled_hr = ((error_code & 0xF) << 23) | hr;
735 fiddled_hr |= 1 << 29; // Set the customer bit.
736
737 return fiddled_hr;
738 }
739
740 HRESULT CustomRegistration(uint16 reg_flags, bool reg, bool is_system) {
741 if (reg && (reg_flags & (ACTIVEDOC | ACTIVEX)))
742 reg_flags |= (TYPELIB | GCF_PROTOCOL);
743
744 // Set the flag that gets checked in AddCommonRGSReplacements before doing
745 // registration work.
746 _AtlModule.do_system_registration_ = is_system;
747
748 typedef HRESULT (*RegistrationFn)(bool reg, bool is_system);
749 struct RegistrationStep {
750 RegistrationStepId id;
751 uint16 condition;
752 RegistrationFn func;
753 };
754 static const RegistrationStep registration_steps[] = {
755 { kStepSecuredMimeHandler, ACTIVEDOC, &RegisterSecuredMimeHandler },
756 { kStepActiveDoc, ACTIVEDOC, &RegisterActiveDoc },
757 { kStepActiveX, ACTIVEX, &RegisterActiveX },
758 { kStepElevationPolicy, (ACTIVEDOC | ACTIVEX), &RegisterElevationPolicy },
759 { kStepProtocol, GCF_PROTOCOL, &RegisterProtocol },
760 { kStepBhoClsid, BHO_CLSID, &RegisterBhoClsid },
761 { kStepBhoRegistration, BHO_REGISTRATION, &RegisterBhoIE },
762 { kStepRegisterTypeLib, TYPELIB, &RegisterTypeLib },
763 { kStepNpapiCleanup, ALL, &RegisterLegacyNPAPICleanup },
764 { kStepAppId, ALL, &RegisterAppId },
765 { kStepUserAgent, ALL, &RegisterUserAgent }
766 };
767
768 HRESULT hr = S_OK;
769
770 bool rollback = false;
771 int failure_step = 0;
772 HRESULT step_hr = S_OK;
773 for (int step = 0; step < arraysize(registration_steps); ++step) {
774 if ((reg_flags & registration_steps[step].condition) != 0) {
775 step_hr = registration_steps[step].func(reg, is_system);
776 if (FAILED(step_hr)) {
777 // Store only the first failing HRESULT with the step value muxed in.
778 if (hr == S_OK) {
779 hr = MuxErrorIntoHRESULT(step_hr, step);
780 }
781
782 // On registration if a step fails, we abort and rollback.
783 if (reg) {
784 rollback = true;
785 failure_step = step;
786 break;
787 }
788 }
789 }
790 }
791
792 if (rollback) {
793 DCHECK(reg);
794 // Rollback the failing action and all preceding ones.
795 for (int step = failure_step; step >= 0; --step) {
796 registration_steps[step].func(!reg, is_system);
797 }
798 }
799
800 return hr;
801 }
802
803 } // namespace
804
805 // DLL Entry Point
806 extern "C" BOOL WINAPI DllMain(HINSTANCE instance,
807 DWORD reason,
808 LPVOID reserved) {
809 UNREFERENCED_PARAMETER(instance);
810 if (reason == DLL_PROCESS_ATTACH) {
811 #ifndef NDEBUG
812 // Silence traces from the ATL registrar to reduce the log noise.
813 ATL::CTrace::s_trace.ChangeCategory(atlTraceRegistrar, 0,
814 ATLTRACESTATUS_DISABLED);
815 #endif
816 InitGoogleUrl();
817
818 g_exit_manager = new base::AtExitManager();
819 CommandLine::Init(0, NULL);
820 InitializeCrashReporting();
821 logging::InitLogging(
822 NULL,
823 logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
824 logging::LOCK_LOG_FILE,
825 logging::DELETE_OLD_LOG_FILE,
826 logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS);
827
828 DllRedirector* dll_redirector = DllRedirector::GetInstance();
829 DCHECK(dll_redirector);
830
831 if (!dll_redirector->RegisterAsFirstCFModule()) {
832 // Someone else was here first, try and get a pointer to their
833 // DllGetClassObject export:
834 g_dll_get_class_object_redir_ptr =
835 dll_redirector->GetDllGetClassObjectPtr();
836 DCHECK(g_dll_get_class_object_redir_ptr != NULL)
837 << "Found CF module with no DllGetClassObject export.";
838 }
839
840 // Enable ETW logging.
841 logging::LogEventProvider::Initialize(kChromeFrameProvider);
842 } else if (reason == DLL_PROCESS_DETACH) {
843 DllRedirector* dll_redirector = DllRedirector::GetInstance();
844 DCHECK(dll_redirector);
845
846 dll_redirector->UnregisterAsFirstCFModule();
847 g_patch_helper.UnpatchIfNeeded();
848 delete g_exit_manager;
849 g_exit_manager = NULL;
850 ShutdownCrashReporting();
851 }
852 return _AtlModule.DllMain(reason, reserved);
853 }
854
855 // Used to determine whether the DLL can be unloaded by OLE
856 STDAPI DllCanUnloadNow() {
857 return _AtlModule.DllCanUnloadNow();
858 }
859
860 // Returns a class factory to create an object of the requested type
861 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) {
862 // If we found another module present when we were loaded, then delegate to
863 // that:
864 if (g_dll_get_class_object_redir_ptr) {
865 return g_dll_get_class_object_redir_ptr(rclsid, riid, ppv);
866 }
867
868 // Enable sniffing and switching only if asked for BHO
869 // (we use BHO to get loaded in IE).
870 if (rclsid == CLSID_ChromeFrameBHO) {
871 g_patch_helper.InitializeAndPatchProtocolsIfNeeded();
872 }
873
874 return _AtlModule.DllGetClassObject(rclsid, riid, ppv);
875 }
876
877 // DllRegisterServer - Adds entries to the system registry
878 STDAPI DllRegisterServer() {
879 uint16 flags = ACTIVEX | ACTIVEDOC | TYPELIB | GCF_PROTOCOL |
880 BHO_CLSID | BHO_REGISTRATION;
881
882 HRESULT hr = CustomRegistration(flags, true, true);
883 if (SUCCEEDED(hr)) {
884 SetupRunOnce();
885 }
886
887 return hr;
888 }
889
890 // DllUnregisterServer - Removes entries from the system registry
891 STDAPI DllUnregisterServer() {
892 HRESULT hr = CustomRegistration(ALL, false, true);
893 return hr;
894 }
895
896 // DllRegisterUserServer - Adds entries to the HKCU hive in the registry.
897 STDAPI DllRegisterUserServer() {
898 UINT flags = ACTIVEX | ACTIVEDOC | TYPELIB | GCF_PROTOCOL |
899 BHO_CLSID | BHO_REGISTRATION;
900
901 HRESULT hr = CustomRegistration(flags, TRUE, false);
902 if (SUCCEEDED(hr)) {
903 SetupRunOnce();
904 }
905
906 return hr;
907 }
908
909 // DllUnregisterUserServer - Removes entries from the HKCU hive in the registry.
910 STDAPI DllUnregisterUserServer() {
911 HRESULT hr = CustomRegistration(ALL, FALSE, false);
912 return hr;
913 }
914
915 // Object entries go here instead of with each object, so that we can move
916 // the objects to a lib. Also reduces magic.
917 OBJECT_ENTRY_AUTO(CLSID_ChromeFrameBHO, Bho)
918 OBJECT_ENTRY_AUTO(__uuidof(ChromeActiveDocument), ChromeActiveDocument)
919 OBJECT_ENTRY_AUTO(__uuidof(ChromeFrame), ChromeFrameActivex)
920 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