// 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 #include #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(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(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(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 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; }