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.
5 #include "chrome_frame/chrome_frame_helper_util.h"
6 #include "chrome_frame/chrome_tab.h"
13 const wchar_t kGetBrowserMessage
[] = L
"GetAutomationObject";
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";
25 bool UtilIsWebBrowserWindow(HWND window_to_check
) {
26 bool is_browser_window
= false;
28 if (!IsWindow(window_to_check
)) {
29 return is_browser_window
;
32 static wchar_t* known_ie_window_classes
[] = {
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;
44 return is_browser_window
;
47 HRESULT
UtilGetWebBrowserObjectFromWindow(HWND window
,
49 void** web_browser_object
) {
50 if (NULL
== web_browser_object
) {
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()) {
64 static const ULONG get_browser_message
=
65 RegisterWindowMessageW(kGetBrowserMessage
);
68 reinterpret_cast<void*>(SendMessage(window
,
70 reinterpret_cast<WPARAM
>(&iid
),
72 if (NULL
!= *web_browser_object
) {
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;
92 return window_matches
;
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;
105 return window_matches
;
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
));
116 struct FindWindowParams
{
118 const wchar_t* class_name_
;
119 const wchar_t* window_name_
;
123 FindWindowParams(HWND parent
,
124 const wchar_t* class_name
,
125 const wchar_t* window_name
,
129 class_name_(class_name
),
130 window_name_(window_name
),
132 thread_id_(thread_id
),
133 process_id_(process_id
) {
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
) {
142 DWORD process_id
= 0;
143 DWORD thread_id
= GetWindowThreadProcessId(window
, &process_id
);
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
150 if ((params
->class_name_
== NULL
||
151 IsWindowOfClass(window
, params
->class_name_
)) &&
152 (params
->window_name_
== NULL
) ||
153 IsNamedWindow(window
, params
->window_name_
)) {
155 params
->window_found_
= window
;
164 BOOL CALLBACK
WndEnumProc(HWND window
, LPARAM lparam
) {
165 FindWindowParams
* params
= reinterpret_cast<FindWindowParams
*>(lparam
);
170 if (WindowMatches(window
, params
)) {
171 // We found a match on a top level window. Return false to stop enumerating.
174 // If criteria not satisfied, let us try child windows.
175 HWND child_window
= RecurseFindWindow(window
,
177 params
->window_name_
,
179 params
->process_id_
);
180 if (child_window
!= NULL
) {
181 // We found the window we are looking for.
182 params
->window_found_
= child_window
;
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
)) {
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_
;
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
,
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
),
214 if (result
== ERROR_SUCCESS
) {
215 if (type
!= REG_SZ
) {
216 result
= ERROR_NOT_SUPPORTED
;
217 } else if (byte_length
== 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';
223 result
= ERROR_MORE_DATA
;
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
));
234 bool bho_registered
= false;
236 wchar_t reg_path_buffer
[MAX_PATH
] = {0};
237 int path_count
= _snwprintf(reg_path_buffer
,
239 kBHORegistrationPathFmt
,
240 bho_clsid_as_string
);
242 if (path_count
> 0) {
243 HKEY reg_handle
= NULL
;
244 LONG result
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
,
249 if (result
== ERROR_SUCCESS
) {
250 RegCloseKey(reg_handle
);
251 bho_registered
= true;
256 return bho_registered
;
259 bool IsSystemLevelChromeFrameInstalled() {
260 bool system_level_installed
= false;
261 HKEY reg_handle
= NULL
;
262 LONG result
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
,
263 kChromeFrameClientKey
,
267 if (result
== ERROR_SUCCESS
) {
268 wchar_t version_buffer
[MAX_PATH
] = {0};
269 result
= ReadValue(reg_handle
,
270 kGoogleUpdateVersionValue
,
273 if (result
== ERROR_SUCCESS
&& version_buffer
[0] != L
'\0') {
274 system_level_installed
= true;
276 RegCloseKey(reg_handle
);
279 return system_level_installed
;