| OLD | NEW |
| 1 // Copyright (c) 2010 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_frame_helper_main.cc : The .exe that bootstraps the | 5 // chrome_frame_helper_main.cc : The .exe that bootstraps the |
| 6 // chrome_frame_helper.dll. | 6 // chrome_frame_helper.dll. |
| 7 // | 7 // |
| 8 // This is a small exe that loads the hook dll to set the event hooks and then | 8 // This is a small exe that loads the hook dll to set the event hooks and then |
| 9 // waits in a message loop. It is intended to be shut down by looking for a | 9 // waits in a message loop. It is intended to be shut down by looking for a |
| 10 // window with the class and title | 10 // window with the class and title |
| 11 // kChromeFrameHelperWindowClassName and kChromeFrameHelperWindowName and then | 11 // kChromeFrameHelperWindowClassName and kChromeFrameHelperWindowName and then |
| 12 // sending that window a WM_CLOSE message. | 12 // sending that window a WM_CLOSE message. |
| 13 // | 13 // |
| 14 | 14 |
| 15 #include <crtdbg.h> | 15 #include <crtdbg.h> |
| 16 #include <objbase.h> |
| 17 #include <stdlib.h> |
| 16 #include <windows.h> | 18 #include <windows.h> |
| 17 | 19 |
| 20 #include "chrome_frame/chrome_frame_helper_util.h" |
| 18 #include "chrome_frame/crash_server_init.h" | 21 #include "chrome_frame/crash_server_init.h" |
| 22 #include "chrome_frame/registry_watcher.h" |
| 23 |
| 24 namespace { |
| 19 | 25 |
| 20 // Window class and window names. | 26 // Window class and window names. |
| 21 const wchar_t kChromeFrameHelperWindowClassName[] = | 27 const wchar_t kChromeFrameHelperWindowClassName[] = |
| 22 L"ChromeFrameHelperWindowClass"; | 28 L"ChromeFrameHelperWindowClass"; |
| 23 const wchar_t kChromeFrameHelperWindowName[] = | 29 const wchar_t kChromeFrameHelperWindowName[] = |
| 24 L"ChromeFrameHelperWindowName"; | 30 L"ChromeFrameHelperWindowName"; |
| 25 | 31 |
| 32 const wchar_t kChromeFrameClientStateKey[] = |
| 33 L"Software\\Google\\Update\\ClientState\\" |
| 34 L"{8BA986DA-5100-405E-AA35-86F34A02ACBF}"; |
| 35 const wchar_t kChromeFrameUninstallCmdExeValue[] = L"UninstallString"; |
| 36 const wchar_t kChromeFrameUninstallCmdArgsValue[] = L"UninstallArguments"; |
| 37 |
| 38 const wchar_t kBHORegistrationPath[] = |
| 39 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer" |
| 40 L"\\Browser Helper Objects"; |
| 41 |
| 42 const wchar_t kStartupArg[] = L"--startup"; |
| 43 const wchar_t kForceUninstall[] = L"--force-uninstall"; |
| 44 |
| 45 HWND g_hwnd = NULL; |
| 46 const UINT kRegistryWatcherChangeMessage = WM_USER + 42; |
| 47 |
| 48 } // namespace |
| 49 |
| 26 // Small helper class that assists in loading the DLL that contains code | 50 // Small helper class that assists in loading the DLL that contains code |
| 27 // to register our event hook callback. Automatically removes the hook and | 51 // to register our event hook callback. Automatically removes the hook and |
| 28 // unloads the DLL on destruction. | 52 // unloads the DLL on destruction. |
| 29 class HookDllLoader { | 53 class HookDllLoader { |
| 30 public: | 54 public: |
| 31 HookDllLoader() : dll_(NULL), start_proc_(NULL), stop_proc_(NULL) {} | 55 HookDllLoader() : dll_(NULL), start_proc_(NULL), stop_proc_(NULL) {} |
| 32 ~HookDllLoader() { | 56 ~HookDllLoader() { |
| 33 if (dll_) { | 57 if (dll_) { |
| 34 Unload(); | 58 Unload(); |
| 35 } | 59 } |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 } | 125 } |
| 102 | 126 |
| 103 LRESULT CALLBACK ChromeFrameHelperWndProc(HWND hwnd, | 127 LRESULT CALLBACK ChromeFrameHelperWndProc(HWND hwnd, |
| 104 UINT message, | 128 UINT message, |
| 105 WPARAM wparam, | 129 WPARAM wparam, |
| 106 LPARAM lparam) { | 130 LPARAM lparam) { |
| 107 switch (message) { | 131 switch (message) { |
| 108 case WM_CREATE: | 132 case WM_CREATE: |
| 109 CloseAllHelperWindowsApartFrom(hwnd); | 133 CloseAllHelperWindowsApartFrom(hwnd); |
| 110 break; | 134 break; |
| 135 case kRegistryWatcherChangeMessage: |
| 136 // A system level Chrome appeared. Fall through: |
| 111 case WM_DESTROY: | 137 case WM_DESTROY: |
| 112 PostQuitMessage(0); | 138 PostQuitMessage(0); |
| 113 break; | 139 break; |
| 114 default: | 140 default: |
| 115 return ::DefWindowProc(hwnd, message, wparam, lparam); | 141 return ::DefWindowProc(hwnd, message, wparam, lparam); |
| 116 } | 142 } |
| 117 return 0; | 143 return 0; |
| 118 } | 144 } |
| 119 | 145 |
| 120 HWND RegisterAndCreateWindow(HINSTANCE hinstance) { | 146 HWND RegisterAndCreateWindow(HINSTANCE hinstance) { |
| 121 WNDCLASSEX wcex = {0}; | 147 WNDCLASSEX wcex = {0}; |
| 122 wcex.cbSize = sizeof(WNDCLASSEX); | 148 wcex.cbSize = sizeof(WNDCLASSEX); |
| 123 wcex.lpfnWndProc = ChromeFrameHelperWndProc; | 149 wcex.lpfnWndProc = ChromeFrameHelperWndProc; |
| 124 wcex.hInstance = GetModuleHandle(NULL); | 150 wcex.hInstance = GetModuleHandle(NULL); |
| 125 wcex.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW+1); | 151 wcex.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW+1); |
| 126 wcex.lpszClassName = kChromeFrameHelperWindowClassName; | 152 wcex.lpszClassName = kChromeFrameHelperWindowClassName; |
| 127 RegisterClassEx(&wcex); | 153 RegisterClassEx(&wcex); |
| 128 | 154 |
| 129 HWND hwnd = CreateWindow(kChromeFrameHelperWindowClassName, | 155 HWND hwnd = CreateWindow(kChromeFrameHelperWindowClassName, |
| 130 kChromeFrameHelperWindowName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, | 156 kChromeFrameHelperWindowName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, |
| 131 CW_USEDEFAULT, 0, NULL, NULL, hinstance, NULL); | 157 CW_USEDEFAULT, 0, NULL, NULL, hinstance, NULL); |
| 132 | 158 |
| 133 return hwnd; | 159 return hwnd; |
| 134 } | 160 } |
| 135 | 161 |
| 162 |
| 163 // This method runs the user-level Chrome Frame uninstall command. This is |
| 164 // intended to allow it to delegate to an existing system-level install. |
| 165 bool UninstallUserLevelChromeFrame() { |
| 166 bool success = false; |
| 167 HKEY reg_handle = NULL; |
| 168 wchar_t reg_path_buffer[MAX_PATH] = {0}; |
| 169 LONG result = RegOpenKeyEx(HKEY_CURRENT_USER, |
| 170 kChromeFrameClientStateKey, |
| 171 0, |
| 172 KEY_QUERY_VALUE, |
| 173 ®_handle); |
| 174 if (result == ERROR_SUCCESS) { |
| 175 wchar_t exe_buffer[MAX_PATH] = {0}; |
| 176 wchar_t args_buffer[MAX_PATH] = {0}; |
| 177 LONG exe_result = ReadValue(reg_handle, |
| 178 kChromeFrameUninstallCmdExeValue, |
| 179 MAX_PATH, |
| 180 exe_buffer); |
| 181 LONG args_result = ReadValue(reg_handle, |
| 182 kChromeFrameUninstallCmdArgsValue, |
| 183 MAX_PATH, |
| 184 args_buffer); |
| 185 RegCloseKey(reg_handle); |
| 186 reg_handle = NULL; |
| 187 |
| 188 if (exe_result == ERROR_SUCCESS && args_result == ERROR_SUCCESS) { |
| 189 STARTUPINFO startup_info = {0}; |
| 190 startup_info.cb = sizeof(startup_info); |
| 191 startup_info.dwFlags = STARTF_USESHOWWINDOW; |
| 192 startup_info.wShowWindow = SW_SHOW; |
| 193 PROCESS_INFORMATION process_info = {0}; |
| 194 |
| 195 // Quote the command string in the args. |
| 196 wchar_t argument_string[MAX_PATH * 3] = {0}; |
| 197 int arg_len = _snwprintf(argument_string, |
| 198 _countof(argument_string) - 1, |
| 199 L"\"%s\" %s %s", |
| 200 exe_buffer, |
| 201 args_buffer, |
| 202 kForceUninstall); |
| 203 |
| 204 if (arg_len > 0 && CreateProcess(exe_buffer, argument_string, |
| 205 NULL, NULL, FALSE, 0, NULL, NULL, |
| 206 &startup_info, &process_info)) { |
| 207 // Close handles. |
| 208 CloseHandle(process_info.hThread); |
| 209 CloseHandle(process_info.hProcess); |
| 210 success = true; |
| 211 } |
| 212 } |
| 213 } |
| 214 |
| 215 return success; |
| 216 } |
| 217 |
| 218 void WaitCallback() { |
| 219 // Check if the Chrome Frame BHO is now in the list of registered BHOs: |
| 220 if (IsBHOLoadingPolicyRegistered()) { |
| 221 PostMessage(g_hwnd, kRegistryWatcherChangeMessage, 0, 0); |
| 222 } |
| 223 } |
| 224 |
| 136 int APIENTRY wWinMain(HINSTANCE hinstance, HINSTANCE, wchar_t*, int show_cmd) { | 225 int APIENTRY wWinMain(HINSTANCE hinstance, HINSTANCE, wchar_t*, int show_cmd) { |
| 137 const wchar_t* cmd_line = ::GetCommandLine(); | 226 const wchar_t* cmd_line = ::GetCommandLine(); |
| 138 google_breakpad::scoped_ptr<google_breakpad::ExceptionHandler> breakpad( | 227 google_breakpad::scoped_ptr<google_breakpad::ExceptionHandler> breakpad( |
| 139 InitializeCrashReporting(cmd_line)); | 228 InitializeCrashReporting(cmd_line)); |
| 140 | 229 |
| 230 if (IsSystemLevelChromeFrameInstalled()) { |
| 231 // If we're running at startup, check for system-level Chrome Frame |
| 232 // installations. If we have one, time |
| 233 // to bail, also schedule user-level CF to be uninstalled at next logon. |
| 234 const wchar_t* cmd_line = ::GetCommandLine(); |
| 235 if (cmd_line && wcsstr(cmd_line, kStartupArg) != NULL) { |
| 236 bool uninstalled = UninstallUserLevelChromeFrame(); |
| 237 _ASSERTE(uninstalled); |
| 238 } |
| 239 return 0; |
| 240 } |
| 241 |
| 141 // Create a window with a known class and title just to listen for WM_CLOSE | 242 // Create a window with a known class and title just to listen for WM_CLOSE |
| 142 // messages that will shut us down. | 243 // messages that will shut us down. |
| 143 HWND hwnd = RegisterAndCreateWindow(hinstance); | 244 g_hwnd = RegisterAndCreateWindow(hinstance); |
| 144 _ASSERTE(hwnd); | 245 _ASSERTE(IsWindow(g_hwnd)); |
| 145 | 246 |
| 146 // Load the hook dll, and set the event hooks. | 247 // Load the hook dll, and set the event hooks. |
| 147 HookDllLoader loader; | 248 HookDllLoader loader; |
| 148 bool loaded = loader.Load(); | 249 bool loaded = loader.Load(); |
| 149 _ASSERTE(loaded); | 250 _ASSERTE(loaded); |
| 150 | 251 |
| 252 // Start up the registry watcher |
| 253 RegistryWatcher registry_watcher(HKEY_LOCAL_MACHINE, kBHORegistrationPath, |
| 254 WaitCallback); |
| 255 bool watching = registry_watcher.StartWatching(); |
| 256 _ASSERTE(watching); |
| 257 |
| 151 if (loaded) { | 258 if (loaded) { |
| 152 MSG msg; | 259 MSG msg; |
| 153 BOOL ret; | 260 BOOL ret; |
| 154 // Main message loop: | 261 // Main message loop: |
| 155 while ((ret = GetMessage(&msg, NULL, 0, 0))) { | 262 while ((ret = GetMessage(&msg, NULL, 0, 0))) { |
| 156 if (ret == -1) { | 263 if (ret == -1) { |
| 157 break; | 264 break; |
| 158 } else { | 265 } else { |
| 159 TranslateMessage(&msg); | 266 TranslateMessage(&msg); |
| 160 DispatchMessage(&msg); | 267 DispatchMessage(&msg); |
| 161 } | 268 } |
| 162 } | 269 } |
| 163 } | 270 } |
| 164 | 271 |
| 165 UnregisterClass(kChromeFrameHelperWindowClassName, hinstance); | 272 UnregisterClass(kChromeFrameHelperWindowClassName, hinstance); |
| 166 return 0; | 273 return 0; |
| 167 } | 274 } |
| OLD | NEW |