| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome_frame/chrome_frame_helper_util.h" | |
| 6 #include "chrome_frame/chrome_tab.h" | |
| 7 | |
| 8 #include <shlwapi.h> | |
| 9 #include <stdio.h> | |
| 10 | |
| 11 namespace { | |
| 12 | |
| 13 const wchar_t kGetBrowserMessage[] = L"GetAutomationObject"; | |
| 14 | |
| 15 const wchar_t kBHORegistrationPathFmt[] = | |
| 16 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer" | |
| 17 L"\\Browser Helper Objects\\%s"; | |
| 18 const wchar_t kChromeFrameClientKey[] = | |
| 19 L"Software\\Google\\Update\\Clients\\" | |
| 20 L"{8BA986DA-5100-405E-AA35-86F34A02ACBF}"; | |
| 21 const wchar_t kGoogleUpdateVersionValue[] = L"pv"; | |
| 22 | |
| 23 } // namespace | |
| 24 | |
| 25 bool UtilIsWebBrowserWindow(HWND window_to_check) { | |
| 26 bool is_browser_window = false; | |
| 27 | |
| 28 if (!IsWindow(window_to_check)) { | |
| 29 return is_browser_window; | |
| 30 } | |
| 31 | |
| 32 static wchar_t* known_ie_window_classes[] = { | |
| 33 L"IEFrame", | |
| 34 L"TabWindowClass" | |
| 35 }; | |
| 36 | |
| 37 for (int i = 0; i < ARRAYSIZE(known_ie_window_classes); i++) { | |
| 38 if (IsWindowOfClass(window_to_check, known_ie_window_classes[i])) { | |
| 39 is_browser_window = true; | |
| 40 break; | |
| 41 } | |
| 42 } | |
| 43 | |
| 44 return is_browser_window; | |
| 45 } | |
| 46 | |
| 47 HRESULT UtilGetWebBrowserObjectFromWindow(HWND window, | |
| 48 REFIID iid, | |
| 49 void** web_browser_object) { | |
| 50 if (NULL == web_browser_object) { | |
| 51 return E_POINTER; | |
| 52 } | |
| 53 | |
| 54 // Check whether this window is really a web browser window. | |
| 55 if (UtilIsWebBrowserWindow(window)) { | |
| 56 // IWebBroswer2 interface pointer can be retrieved from the browser | |
| 57 // window by simply sending a registered message "GetAutomationObject" | |
| 58 // Note that since we are sending a message to parent window make sure that | |
| 59 // it is in the same thread. | |
| 60 if (GetWindowThreadProcessId(window, NULL) != GetCurrentThreadId()) { | |
| 61 return E_UNEXPECTED; | |
| 62 } | |
| 63 | |
| 64 static const ULONG get_browser_message = | |
| 65 RegisterWindowMessageW(kGetBrowserMessage); | |
| 66 | |
| 67 *web_browser_object = | |
| 68 reinterpret_cast<void*>(SendMessage(window, | |
| 69 get_browser_message, | |
| 70 reinterpret_cast<WPARAM>(&iid), | |
| 71 NULL)); | |
| 72 if (NULL != *web_browser_object) { | |
| 73 return S_OK; | |
| 74 } | |
| 75 } else { | |
| 76 return E_INVALIDARG; | |
| 77 } | |
| 78 return E_NOINTERFACE; | |
| 79 } | |
| 80 | |
| 81 bool IsWindowOfClass(HWND window_to_check, const wchar_t* window_class) { | |
| 82 bool window_matches = false; | |
| 83 const int buf_size = MAX_PATH; | |
| 84 wchar_t buffer[buf_size] = {0}; | |
| 85 DWORD size = GetClassNameW(window_to_check, buffer, buf_size); | |
| 86 // If the window name is any longer than this, it isn't the one we want. | |
| 87 if (size < (buf_size - 1)) { | |
| 88 if (!lstrcmpiW(window_class, buffer)) { | |
| 89 window_matches = true; | |
| 90 } | |
| 91 } | |
| 92 return window_matches; | |
| 93 } | |
| 94 | |
| 95 bool IsNamedWindow(HWND window, const wchar_t* window_name) { | |
| 96 bool window_matches = false; | |
| 97 const int buf_size = MAX_PATH; | |
| 98 wchar_t buffer[buf_size] = {0}; | |
| 99 DWORD size = GetWindowText(window, buffer, buf_size); | |
| 100 if (size < (buf_size - 1)) { | |
| 101 if (!lstrcmpiW(window_name, buffer)) { | |
| 102 window_matches = true; | |
| 103 } | |
| 104 } | |
| 105 return window_matches; | |
| 106 } | |
| 107 | |
| 108 bool IsNamedProcess(const wchar_t* process_name) { | |
| 109 wchar_t file_path[2048] = {0}; | |
| 110 GetModuleFileName(NULL, file_path, 2047); | |
| 111 wchar_t* file_name = PathFindFileName(file_path); | |
| 112 return (0 == lstrcmpiW(file_name, process_name)); | |
| 113 } | |
| 114 | |
| 115 namespace { | |
| 116 struct FindWindowParams { | |
| 117 HWND parent_; | |
| 118 const wchar_t* class_name_; | |
| 119 const wchar_t* window_name_; | |
| 120 HWND window_found_; | |
| 121 DWORD thread_id_; | |
| 122 DWORD process_id_; | |
| 123 FindWindowParams(HWND parent, | |
| 124 const wchar_t* class_name, | |
| 125 const wchar_t* window_name, | |
| 126 DWORD thread_id, | |
| 127 DWORD process_id) | |
| 128 : parent_(parent), | |
| 129 class_name_(class_name), | |
| 130 window_name_(window_name), | |
| 131 window_found_(NULL), | |
| 132 thread_id_(thread_id), | |
| 133 process_id_(process_id) { | |
| 134 } | |
| 135 }; | |
| 136 | |
| 137 // Checks a window against a set of parameters defined in params. If the | |
| 138 // window matches, fills in params->window_found_ with the HWND of the window | |
| 139 // and returns true. Returns false otherwise. | |
| 140 bool WindowMatches(HWND window, FindWindowParams* params) { | |
| 141 bool found = false; | |
| 142 DWORD process_id = 0; | |
| 143 DWORD thread_id = GetWindowThreadProcessId(window, &process_id); | |
| 144 | |
| 145 // First check that the PID and TID match if we're interested. | |
| 146 if (params->process_id_ == 0 || params->process_id_ == process_id) { | |
| 147 if (params->thread_id_ == 0 || params->thread_id_ == thread_id) { | |
| 148 // Then check that we match on class and window names, again only if | |
| 149 // we're interested. | |
| 150 if ((params->class_name_ == NULL || | |
| 151 IsWindowOfClass(window, params->class_name_)) && | |
| 152 (params->window_name_ == NULL) || | |
| 153 IsNamedWindow(window, params->window_name_)) { | |
| 154 found = true; | |
| 155 params->window_found_ = window; | |
| 156 } | |
| 157 } | |
| 158 } | |
| 159 return found; | |
| 160 } | |
| 161 | |
| 162 } // namespace | |
| 163 | |
| 164 BOOL CALLBACK WndEnumProc(HWND window, LPARAM lparam) { | |
| 165 FindWindowParams* params = reinterpret_cast<FindWindowParams *>(lparam); | |
| 166 if (!params) { | |
| 167 return FALSE; | |
| 168 } | |
| 169 | |
| 170 if (WindowMatches(window, params)) { | |
| 171 // We found a match on a top level window. Return false to stop enumerating. | |
| 172 return FALSE; | |
| 173 } else { | |
| 174 // If criteria not satisfied, let us try child windows. | |
| 175 HWND child_window = RecurseFindWindow(window, | |
| 176 params->class_name_, | |
| 177 params->window_name_, | |
| 178 params->thread_id_, | |
| 179 params->process_id_); | |
| 180 if (child_window != NULL) { | |
| 181 // We found the window we are looking for. | |
| 182 params->window_found_ = child_window; | |
| 183 return FALSE; | |
| 184 } | |
| 185 return TRUE; | |
| 186 } | |
| 187 } | |
| 188 | |
| 189 HWND RecurseFindWindow(HWND parent, | |
| 190 const wchar_t* class_name, | |
| 191 const wchar_t* window_name, | |
| 192 DWORD thread_id_to_match, | |
| 193 DWORD process_id_to_match) { | |
| 194 if ((class_name == NULL) && (window_name == NULL)) { | |
| 195 return NULL; | |
| 196 } | |
| 197 FindWindowParams params(parent, class_name, window_name, | |
| 198 thread_id_to_match, process_id_to_match); | |
| 199 EnumChildWindows(parent, WndEnumProc, reinterpret_cast<LPARAM>(¶ms)); | |
| 200 return params.window_found_; | |
| 201 } | |
| 202 | |
| 203 // TODO(robertshield): This is stolen shamelessly from mini_installer.cc. | |
| 204 // Refactor this before (more) bad things happen. | |
| 205 LONG ReadValue(HKEY key, | |
| 206 const wchar_t* value_name, | |
| 207 size_t value_size, | |
| 208 wchar_t* value) { | |
| 209 DWORD type; | |
| 210 DWORD byte_length = static_cast<DWORD>(value_size * sizeof(wchar_t)); | |
| 211 LONG result = ::RegQueryValueEx(key, value_name, NULL, &type, | |
| 212 reinterpret_cast<BYTE*>(value), | |
| 213 &byte_length); | |
| 214 if (result == ERROR_SUCCESS) { | |
| 215 if (type != REG_SZ) { | |
| 216 result = ERROR_NOT_SUPPORTED; | |
| 217 } else if (byte_length == 0) { | |
| 218 *value = L'\0'; | |
| 219 } else if (value[byte_length/sizeof(wchar_t) - 1] != L'\0') { | |
| 220 if ((byte_length / sizeof(wchar_t)) < value_size) | |
| 221 value[byte_length / sizeof(wchar_t)] = L'\0'; | |
| 222 else | |
| 223 result = ERROR_MORE_DATA; | |
| 224 } | |
| 225 } | |
| 226 return result; | |
| 227 } | |
| 228 | |
| 229 bool IsBHOLoadingPolicyRegistered() { | |
| 230 wchar_t bho_clsid_as_string[MAX_PATH] = {0}; | |
| 231 int count = StringFromGUID2(CLSID_ChromeFrameBHO, bho_clsid_as_string, | |
| 232 ARRAYSIZE(bho_clsid_as_string)); | |
| 233 | |
| 234 bool bho_registered = false; | |
| 235 if (count > 0) { | |
| 236 wchar_t reg_path_buffer[MAX_PATH] = {0}; | |
| 237 int path_count = _snwprintf(reg_path_buffer, | |
| 238 MAX_PATH - 1, | |
| 239 kBHORegistrationPathFmt, | |
| 240 bho_clsid_as_string); | |
| 241 | |
| 242 if (path_count > 0) { | |
| 243 HKEY reg_handle = NULL; | |
| 244 LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, | |
| 245 reg_path_buffer, | |
| 246 0, | |
| 247 KEY_QUERY_VALUE, | |
| 248 ®_handle); | |
| 249 if (result == ERROR_SUCCESS) { | |
| 250 RegCloseKey(reg_handle); | |
| 251 bho_registered = true; | |
| 252 } | |
| 253 } | |
| 254 } | |
| 255 | |
| 256 return bho_registered; | |
| 257 } | |
| 258 | |
| 259 bool IsSystemLevelChromeFrameInstalled() { | |
| 260 bool system_level_installed = false; | |
| 261 HKEY reg_handle = NULL; | |
| 262 LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, | |
| 263 kChromeFrameClientKey, | |
| 264 0, | |
| 265 KEY_QUERY_VALUE, | |
| 266 ®_handle); | |
| 267 if (result == ERROR_SUCCESS) { | |
| 268 wchar_t version_buffer[MAX_PATH] = {0}; | |
| 269 result = ReadValue(reg_handle, | |
| 270 kGoogleUpdateVersionValue, | |
| 271 MAX_PATH, | |
| 272 version_buffer); | |
| 273 if (result == ERROR_SUCCESS && version_buffer[0] != L'\0') { | |
| 274 system_level_installed = true; | |
| 275 } | |
| 276 RegCloseKey(reg_handle); | |
| 277 } | |
| 278 | |
| 279 return system_level_installed; | |
| 280 } | |
| 281 | |
| OLD | NEW |