| // Copyright (c) 2010 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. |
| // |
| // chrome_frame_helper_main.cc : The .exe that bootstraps the |
| // chrome_frame_helper.dll. |
| // |
| // This is a small exe that loads the hook dll to set the event hooks and then |
| // waits in a message loop. It is intended to be shut down by looking for a |
| // window with the class and title |
| // kChromeFrameHelperWindowClassName and kChromeFrameHelperWindowName and then |
| // sending that window a WM_CLOSE message. |
| // |
| |
| #include <crtdbg.h> |
| #include <windows.h> |
| |
| #include "chrome_frame/crash_server_init.h" |
| |
| // Window class and window names. |
| const wchar_t kChromeFrameHelperWindowClassName[] = |
| L"ChromeFrameHelperWindowClass"; |
| const wchar_t kChromeFrameHelperWindowName[] = |
| L"ChromeFrameHelperWindowName"; |
| |
| // 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. |
| class HookDllLoader { |
| public: |
| HookDllLoader() : dll_(NULL), start_proc_(NULL), stop_proc_(NULL) {} |
| ~HookDllLoader() { |
| if (dll_) { |
| Unload(); |
| } |
| } |
| |
| bool Load() { |
| dll_ = LoadLibrary(L"chrome_frame_helper.dll"); |
| if (dll_) { |
| start_proc_ = GetProcAddress(dll_, "StartUserModeBrowserInjection"); |
| stop_proc_ = GetProcAddress(dll_, "StopUserModeBrowserInjection"); |
| } |
| |
| bool result = true; |
| if (!start_proc_ || !stop_proc_) { |
| _ASSERTE(L"failed to load hook dll."); |
| result = false; |
| } else { |
| if (FAILED(start_proc_())) { |
| _ASSERTE(L"failed to initialize hook dll."); |
| result = false; |
| } |
| } |
| return result; |
| } |
| |
| void Unload() { |
| if (stop_proc_) { |
| stop_proc_(); |
| } |
| if (dll_) { |
| FreeLibrary(dll_); |
| } |
| } |
| |
| private: |
| HMODULE dll_; |
| PROC start_proc_; |
| PROC stop_proc_; |
| }; |
| |
| // Checks the window title and then class of hwnd. If they match with that |
| // of a chrome_frame_helper.exe window, then add it to the list of windows |
| // pointed to by lparam. |
| BOOL CALLBACK CloseHelperWindowsEnumProc(HWND hwnd, LPARAM lparam) { |
| _ASSERTE(lparam != 0); |
| |
| wchar_t title_buffer[MAX_PATH] = {0}; |
| if (GetWindowText(hwnd, title_buffer, MAX_PATH)) { |
| if (lstrcmpiW(title_buffer, kChromeFrameHelperWindowName) == 0) { |
| wchar_t class_buffer[MAX_PATH] = {0}; |
| if (GetClassName(hwnd, class_buffer, MAX_PATH)) { |
| if (lstrcmpiW(class_buffer, kChromeFrameHelperWindowClassName) == 0) { |
| if (hwnd != reinterpret_cast<HWND>(lparam)) { |
| PostMessage(hwnd, WM_CLOSE, 0, 0); |
| } |
| } |
| } |
| } |
| } |
| |
| return TRUE; |
| } |
| |
| // Enumerates all top level windows, looking for those that look like a |
| // Chrome Frame helper window. It then closes all of them except for |
| // except_me. |
| void CloseAllHelperWindowsApartFrom(HWND except_me) { |
| EnumWindows(CloseHelperWindowsEnumProc, reinterpret_cast<LPARAM>(except_me)); |
| } |
| |
| LRESULT CALLBACK ChromeFrameHelperWndProc(HWND hwnd, |
| UINT message, |
| WPARAM wparam, |
| LPARAM lparam) { |
| switch (message) { |
| case WM_CREATE: |
| CloseAllHelperWindowsApartFrom(hwnd); |
| break; |
| case WM_DESTROY: |
| PostQuitMessage(0); |
| break; |
| default: |
| return ::DefWindowProc(hwnd, message, wparam, lparam); |
| } |
| return 0; |
| } |
| |
| HWND RegisterAndCreateWindow(HINSTANCE hinstance) { |
| WNDCLASSEX wcex = {0}; |
| wcex.cbSize = sizeof(WNDCLASSEX); |
| wcex.lpfnWndProc = ChromeFrameHelperWndProc; |
| wcex.hInstance = GetModuleHandle(NULL); |
| wcex.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW+1); |
| wcex.lpszClassName = kChromeFrameHelperWindowClassName; |
| RegisterClassEx(&wcex); |
| |
| HWND hwnd = CreateWindow(kChromeFrameHelperWindowClassName, |
| kChromeFrameHelperWindowName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, |
| CW_USEDEFAULT, 0, NULL, NULL, hinstance, NULL); |
| |
| return hwnd; |
| } |
| |
| 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)); |
| |
| // 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); |
| |
| // Load the hook dll, and set the event hooks. |
| HookDllLoader loader; |
| bool loaded = loader.Load(); |
| _ASSERTE(loaded); |
| |
| if (loaded) { |
| MSG msg; |
| BOOL ret; |
| // Main message loop: |
| while ((ret = GetMessage(&msg, NULL, 0, 0))) { |
| if (ret == -1) { |
| break; |
| } else { |
| TranslateMessage(&msg); |
| DispatchMessage(&msg); |
| } |
| } |
| } |
| |
| return 0; |
| } |