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