blob: 0b6bc7306f0fe68c50b21f74870ed0576b1b4690 [file] [log] [blame]
[email protected]9ceda772010-08-30 15:34:111// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4//
5// chrome_frame_helper_main.cc : The .exe that bootstraps the
6// chrome_frame_helper.dll.
7//
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
10// window with the class and title
11// kChromeFrameHelperWindowClassName and kChromeFrameHelperWindowName and then
12// sending that window a WM_CLOSE message.
13//
14
15#include <crtdbg.h>
16#include <windows.h>
17
[email protected]e4fe427b2010-09-03 19:57:4218#include "chrome_frame/crash_server_init.h"
19
[email protected]9ceda772010-08-30 15:34:1120// Window class and window names.
21const wchar_t kChromeFrameHelperWindowClassName[] =
22 L"ChromeFrameHelperWindowClass";
23const wchar_t kChromeFrameHelperWindowName[] =
24 L"ChromeFrameHelperWindowName";
25
26// Small helper class that assists in loading the DLL that contains code
27// to register our event hook callback. Automatically removes the hook and
28// unloads the DLL on destruction.
29class HookDllLoader {
30 public:
31 HookDllLoader() : dll_(NULL), start_proc_(NULL), stop_proc_(NULL) {}
32 ~HookDllLoader() {
33 if (dll_) {
34 Unload();
35 }
36 }
37
38 bool Load() {
39 dll_ = LoadLibrary(L"chrome_frame_helper.dll");
40 if (dll_) {
41 start_proc_ = GetProcAddress(dll_, "StartUserModeBrowserInjection");
42 stop_proc_ = GetProcAddress(dll_, "StopUserModeBrowserInjection");
43 }
44
45 bool result = true;
46 if (!start_proc_ || !stop_proc_) {
47 _ASSERTE(L"failed to load hook dll.");
48 result = false;
49 } else {
50 if (FAILED(start_proc_())) {
51 _ASSERTE(L"failed to initialize hook dll.");
52 result = false;
53 }
54 }
55 return result;
56 }
57
58 void Unload() {
59 if (stop_proc_) {
60 stop_proc_();
61 }
62 if (dll_) {
63 FreeLibrary(dll_);
64 }
65 }
66
67 private:
68 HMODULE dll_;
69 PROC start_proc_;
70 PROC stop_proc_;
71};
72
[email protected]9283f272010-09-08 18:23:3073// Checks the window title and then class of hwnd. If they match with that
74// of a chrome_frame_helper.exe window, then add it to the list of windows
75// pointed to by lparam.
76BOOL CALLBACK CloseHelperWindowsEnumProc(HWND hwnd, LPARAM lparam) {
77 _ASSERTE(lparam != 0);
78
79 wchar_t title_buffer[MAX_PATH] = {0};
80 if (GetWindowText(hwnd, title_buffer, MAX_PATH)) {
81 if (lstrcmpiW(title_buffer, kChromeFrameHelperWindowName) == 0) {
82 wchar_t class_buffer[MAX_PATH] = {0};
83 if (GetClassName(hwnd, class_buffer, MAX_PATH)) {
84 if (lstrcmpiW(class_buffer, kChromeFrameHelperWindowClassName) == 0) {
85 if (hwnd != reinterpret_cast<HWND>(lparam)) {
86 PostMessage(hwnd, WM_CLOSE, 0, 0);
87 }
88 }
89 }
90 }
91 }
92
93 return TRUE;
94}
95
96// Enumerates all top level windows, looking for those that look like a
97// Chrome Frame helper window. It then closes all of them except for
98// except_me.
99void CloseAllHelperWindowsApartFrom(HWND except_me) {
100 EnumWindows(CloseHelperWindowsEnumProc, reinterpret_cast<LPARAM>(except_me));
101}
[email protected]9ceda772010-08-30 15:34:11102
103LRESULT CALLBACK ChromeFrameHelperWndProc(HWND hwnd,
104 UINT message,
105 WPARAM wparam,
106 LPARAM lparam) {
107 switch (message) {
[email protected]9283f272010-09-08 18:23:30108 case WM_CREATE:
109 CloseAllHelperWindowsApartFrom(hwnd);
110 break;
[email protected]9ceda772010-08-30 15:34:11111 case WM_DESTROY:
112 PostQuitMessage(0);
113 break;
114 default:
115 return ::DefWindowProc(hwnd, message, wparam, lparam);
116 }
117 return 0;
118}
119
120HWND RegisterAndCreateWindow(HINSTANCE hinstance) {
121 WNDCLASSEX wcex = {0};
122 wcex.cbSize = sizeof(WNDCLASSEX);
123 wcex.lpfnWndProc = ChromeFrameHelperWndProc;
124 wcex.hInstance = GetModuleHandle(NULL);
125 wcex.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW+1);
126 wcex.lpszClassName = kChromeFrameHelperWindowClassName;
127 RegisterClassEx(&wcex);
128
129 HWND hwnd = CreateWindow(kChromeFrameHelperWindowClassName,
130 kChromeFrameHelperWindowName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0,
131 CW_USEDEFAULT, 0, NULL, NULL, hinstance, NULL);
132
133 return hwnd;
134}
135
136int APIENTRY wWinMain(HINSTANCE hinstance, HINSTANCE, wchar_t*, int show_cmd) {
[email protected]e4fe427b2010-09-03 19:57:42137 const wchar_t* cmd_line = ::GetCommandLine();
138 google_breakpad::scoped_ptr<google_breakpad::ExceptionHandler> breakpad(
139 InitializeCrashReporting(cmd_line));
[email protected]9ceda772010-08-30 15:34:11140
141 // Create a window with a known class and title just to listen for WM_CLOSE
142 // messages that will shut us down.
143 HWND hwnd = RegisterAndCreateWindow(hinstance);
144 _ASSERTE(hwnd);
145
146 // Load the hook dll, and set the event hooks.
147 HookDllLoader loader;
148 bool loaded = loader.Load();
149 _ASSERTE(loaded);
150
151 if (loaded) {
152 MSG msg;
153 BOOL ret;
154 // Main message loop:
155 while ((ret = GetMessage(&msg, NULL, 0, 0))) {
156 if (ret == -1) {
157 break;
158 } else {
159 TranslateMessage(&msg);
160 DispatchMessage(&msg);
161 }
162 }
163 }
164
165 return 0;
166}