| Index: chrome_frame/chrome_frame_helper_main.cc
|
| ===================================================================
|
| --- chrome_frame/chrome_frame_helper_main.cc (revision 86605)
|
| +++ chrome_frame/chrome_frame_helper_main.cc (working copy)
|
| @@ -1,4 +1,4 @@
|
| -// Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
| //
|
| @@ -13,16 +13,40 @@
|
| //
|
|
|
| #include <crtdbg.h>
|
| +#include <objbase.h>
|
| +#include <stdlib.h>
|
| #include <windows.h>
|
|
|
| +#include "chrome_frame/chrome_frame_helper_util.h"
|
| #include "chrome_frame/crash_server_init.h"
|
| +#include "chrome_frame/registry_watcher.h"
|
|
|
| +namespace {
|
| +
|
| // Window class and window names.
|
| const wchar_t kChromeFrameHelperWindowClassName[] =
|
| L"ChromeFrameHelperWindowClass";
|
| const wchar_t kChromeFrameHelperWindowName[] =
|
| L"ChromeFrameHelperWindowName";
|
|
|
| +const wchar_t kChromeFrameClientStateKey[] =
|
| + L"Software\\Google\\Update\\ClientState\\"
|
| + L"{8BA986DA-5100-405E-AA35-86F34A02ACBF}";
|
| +const wchar_t kChromeFrameUninstallCmdExeValue[] = L"UninstallString";
|
| +const wchar_t kChromeFrameUninstallCmdArgsValue[] = L"UninstallArguments";
|
| +
|
| +const wchar_t kBHORegistrationPath[] =
|
| + L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer"
|
| + L"\\Browser Helper Objects";
|
| +
|
| +const wchar_t kStartupArg[] = L"--startup";
|
| +const wchar_t kForceUninstall[] = L"--force-uninstall";
|
| +
|
| +HWND g_hwnd = NULL;
|
| +const UINT kRegistryWatcherChangeMessage = WM_USER + 42;
|
| +
|
| +} // namespace
|
| +
|
| // Small helper class that assists in loading the DLL that contains code
|
| // to register our event hook callback. Automatically removes the hook and
|
| // unloads the DLL on destruction.
|
| @@ -108,6 +132,8 @@
|
| case WM_CREATE:
|
| CloseAllHelperWindowsApartFrom(hwnd);
|
| break;
|
| + case kRegistryWatcherChangeMessage:
|
| + // A system level Chrome appeared. Fall through:
|
| case WM_DESTROY:
|
| PostQuitMessage(0);
|
| break;
|
| @@ -133,21 +159,102 @@
|
| return hwnd;
|
| }
|
|
|
| +
|
| +// This method runs the user-level Chrome Frame uninstall command. This is
|
| +// intended to allow it to delegate to an existing system-level install.
|
| +bool UninstallUserLevelChromeFrame() {
|
| + bool success = false;
|
| + HKEY reg_handle = NULL;
|
| + wchar_t reg_path_buffer[MAX_PATH] = {0};
|
| + LONG result = RegOpenKeyEx(HKEY_CURRENT_USER,
|
| + kChromeFrameClientStateKey,
|
| + 0,
|
| + KEY_QUERY_VALUE,
|
| + ®_handle);
|
| + if (result == ERROR_SUCCESS) {
|
| + wchar_t exe_buffer[MAX_PATH] = {0};
|
| + wchar_t args_buffer[MAX_PATH] = {0};
|
| + LONG exe_result = ReadValue(reg_handle,
|
| + kChromeFrameUninstallCmdExeValue,
|
| + MAX_PATH,
|
| + exe_buffer);
|
| + LONG args_result = ReadValue(reg_handle,
|
| + kChromeFrameUninstallCmdArgsValue,
|
| + MAX_PATH,
|
| + args_buffer);
|
| + RegCloseKey(reg_handle);
|
| + reg_handle = NULL;
|
| +
|
| + if (exe_result == ERROR_SUCCESS && args_result == ERROR_SUCCESS) {
|
| + STARTUPINFO startup_info = {0};
|
| + startup_info.cb = sizeof(startup_info);
|
| + startup_info.dwFlags = STARTF_USESHOWWINDOW;
|
| + startup_info.wShowWindow = SW_SHOW;
|
| + PROCESS_INFORMATION process_info = {0};
|
| +
|
| + // Quote the command string in the args.
|
| + wchar_t argument_string[MAX_PATH * 3] = {0};
|
| + int arg_len = _snwprintf(argument_string,
|
| + _countof(argument_string) - 1,
|
| + L"\"%s\" %s %s",
|
| + exe_buffer,
|
| + args_buffer,
|
| + kForceUninstall);
|
| +
|
| + if (arg_len > 0 && CreateProcess(exe_buffer, argument_string,
|
| + NULL, NULL, FALSE, 0, NULL, NULL,
|
| + &startup_info, &process_info)) {
|
| + // Close handles.
|
| + CloseHandle(process_info.hThread);
|
| + CloseHandle(process_info.hProcess);
|
| + success = true;
|
| + }
|
| + }
|
| + }
|
| +
|
| + return success;
|
| +}
|
| +
|
| +void WaitCallback() {
|
| + // Check if the Chrome Frame BHO is now in the list of registered BHOs:
|
| + if (IsBHOLoadingPolicyRegistered()) {
|
| + PostMessage(g_hwnd, kRegistryWatcherChangeMessage, 0, 0);
|
| + }
|
| +}
|
| +
|
| int APIENTRY wWinMain(HINSTANCE hinstance, HINSTANCE, wchar_t*, int show_cmd) {
|
| const wchar_t* cmd_line = ::GetCommandLine();
|
| google_breakpad::scoped_ptr<google_breakpad::ExceptionHandler> breakpad(
|
| InitializeCrashReporting(cmd_line));
|
|
|
| + if (IsSystemLevelChromeFrameInstalled()) {
|
| + // If we're running at startup, check for system-level Chrome Frame
|
| + // installations. If we have one, time
|
| + // to bail, also schedule user-level CF to be uninstalled at next logon.
|
| + const wchar_t* cmd_line = ::GetCommandLine();
|
| + if (cmd_line && wcsstr(cmd_line, kStartupArg) != NULL) {
|
| + bool uninstalled = UninstallUserLevelChromeFrame();
|
| + _ASSERTE(uninstalled);
|
| + }
|
| + return 0;
|
| + }
|
| +
|
| // Create a window with a known class and title just to listen for WM_CLOSE
|
| // messages that will shut us down.
|
| - HWND hwnd = RegisterAndCreateWindow(hinstance);
|
| - _ASSERTE(hwnd);
|
| + g_hwnd = RegisterAndCreateWindow(hinstance);
|
| + _ASSERTE(IsWindow(g_hwnd));
|
|
|
| // Load the hook dll, and set the event hooks.
|
| HookDllLoader loader;
|
| bool loaded = loader.Load();
|
| _ASSERTE(loaded);
|
|
|
| + // Start up the registry watcher
|
| + RegistryWatcher registry_watcher(HKEY_LOCAL_MACHINE, kBHORegistrationPath,
|
| + WaitCallback);
|
| + bool watching = registry_watcher.StartWatching();
|
| + _ASSERTE(watching);
|
| +
|
| if (loaded) {
|
| MSG msg;
|
| BOOL ret;
|
|
|