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

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