ash
base
breakpad
build
chrome
chrome_frame
cfinstall
common
crash_reporting
infobars
installer_util
locales
ready_mode
resources
test
tools
CFInstall.js
CFInstance.js
OWNERS
bho.cc
bho.h
bho.rgs
bho_loader.cc
bho_loader.h
bind_context_info.cc
bind_context_info.h
bind_status_callback_impl.cc
bind_status_callback_impl.h
buggy_bho_handling.cc
buggy_bho_handling.h
cfproxy.h
cfproxy_factory.cc
cfproxy_private.h
cfproxy_proxy.cc
cfproxy_support.cc
cfproxy_test.cc
chrome_active_document.cc
chrome_active_document.h
chrome_active_document.rgs
chrome_frame.croc
chrome_frame.gyp
chrome_frame_activex.cc
chrome_frame_activex.h
chrome_frame_activex.rgs
chrome_frame_activex_base.h
chrome_frame_automation.cc
chrome_frame_automation.h
chrome_frame_delegate.cc
chrome_frame_delegate.h
chrome_frame_elevation.rgs
chrome_frame_helper_dll.cc
chrome_frame_helper_dll.def
chrome_frame_helper_main.cc
chrome_frame_helper_util.cc
chrome_frame_helper_util.h
chrome_frame_helper_version.rc
chrome_frame_launcher.gyp
chrome_frame_npapi.rgs
chrome_frame_plugin.cc
chrome_frame_plugin.h
chrome_frame_reporting.cc
chrome_frame_reporting.h
chrome_frame_unittest_main.cc
chrome_launcher.cc
chrome_launcher.h
chrome_launcher_main.cc
chrome_launcher_unittest.cc
chrome_launcher_utils.cc
chrome_launcher_utils.h
chrome_launcher_version.rc
chrome_protocol.cc
chrome_protocol.h
chrome_protocol.rgs
chrome_tab.cc
chrome_tab.def
chrome_tab.idl
chrome_tab.rgs
chrome_tab_version.rc
chrome_tab_version.rc.version
com_message_event.cc
com_message_event.h
com_type_info_holder.cc
com_type_info_holder.h
combine_libs.py
crash_server_init.cc
crash_server_init.h
custom_sync_call_context.cc
custom_sync_call_context.h
delete_chrome_history.cc
delete_chrome_history.h
dll_redirector.cc
dll_redirector.h
event_hooker.cc
event_hooker.h
exception_barrier.cc
exception_barrier.h
exception_barrier_lowlevel.asm
external_tab.cc
external_tab.h
external_tab_test.cc
extra_system_apis.h
find_dialog.cc
find_dialog.h
frame.html
frame_w_controls.html
function_stub.cc
function_stub.h
function_stub_unittest.cc
host.html
host_w_controls.html
html_private_window_impl.h
html_utils.cc
html_utils.h
html_window_impl.h
http_negotiate.cc
http_negotiate.h
ie8_types.h
iids.cc
metrics_service.cc
metrics_service.h
navigation_constraints.cc
navigation_constraints.h
plugin_url_request.cc
plugin_url_request.h
policy_settings.cc
policy_settings.h
precompiled.cc
precompiled.h
protocol_sink_wrap.cc
protocol_sink_wrap.h
register_bho.rgs
registry_watcher.cc
registry_watcher.h
renderer_glue.cc
resource.h
simple_resource_loader.cc
simple_resource_loader.h
smoke_test.bat
stream_impl.cc
stream_impl.h
support.gyp
sync_msg_reply_dispatcher.cc
sync_msg_reply_dispatcher.h
task_marshaller.cc
task_marshaller.h
test_utils.cc
test_utils.h
unittest_precompile.cc
unittest_precompile.h
update_launcher.cc
update_launcher.h
urlmon_bind_status_callback.cc
urlmon_bind_status_callback.h
urlmon_moniker.cc
urlmon_moniker.h
urlmon_upload_data_stream.cc
urlmon_upload_data_stream.h
urlmon_upload_data_stream_unittest.cc
urlmon_url_request.cc
urlmon_url_request.h
urlmon_url_request_private.h
utils.cc
utils.h
vtable_patch_manager.cc
vtable_patch_manager.h
vtable_patch_manager_unittest.cc
cloud_print
content
courgette
crypto
dbus
google_update
gpu
ipc
jingle
media
native_client_sdk
net
ppapi
printing
remoting
sandbox
sdch
skia
sql
testing
third_party
tools
ui
webkit
.DEPS.git
.gitignore
AUTHORS
DEPS
LICENSE
OWNERS
PRESUBMIT.py
WATCHLISTS
codereview.settings

Also add a more helpful error message when failing to register the Chrome Frame dll. Review URL: http://codereview.chromium.org/8013001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@102780 0039d316-1c4b-4281-b951-d872f2087c98
355 lines
12 KiB
C++
355 lines
12 KiB
C++
// Copyright (c) 2011 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.
|
|
|
|
#include <algorithm>
|
|
|
|
#include "chrome_frame/test_utils.h"
|
|
|
|
#include <atlbase.h>
|
|
#include <atlwin.h>
|
|
#include <winternl.h>
|
|
|
|
#include "base/file_path.h"
|
|
#include "base/file_util.h"
|
|
#include "base/logging.h"
|
|
#include "base/path_service.h"
|
|
#include "base/process_util.h"
|
|
#include "base/string_util.h"
|
|
#include "base/win/scoped_handle.h"
|
|
#include "chrome/common/chrome_paths.h"
|
|
#include "chrome/common/chrome_switches.h"
|
|
#include "chrome_frame/test/chrome_frame_test_utils.h"
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
|
|
const wchar_t kChromeFrameDllName[] = L"npchrome_frame.dll";
|
|
const wchar_t kChromeLauncherExeName[] = L"chrome_launcher.exe";
|
|
|
|
FilePath GetChromeFrameBuildPath() {
|
|
FilePath build_path;
|
|
PathService::Get(chrome::DIR_APP, &build_path);
|
|
|
|
FilePath dll_path = build_path.Append(kChromeFrameDllName);
|
|
|
|
if (!file_util::PathExists(dll_path)) {
|
|
// Well, dang.. try looking in the current directory.
|
|
dll_path = build_path.Append(kChromeFrameDllName);
|
|
}
|
|
|
|
if (!file_util::PathExists(dll_path)) {
|
|
// No luck, return something empty.
|
|
dll_path = FilePath();
|
|
}
|
|
|
|
return dll_path;
|
|
}
|
|
|
|
bool ScopedChromeFrameRegistrar::register_chrome_path_provider_ = false;
|
|
|
|
// static
|
|
void ScopedChromeFrameRegistrar::RegisterDefaults() {
|
|
if (!register_chrome_path_provider_) {
|
|
chrome::RegisterPathProvider();
|
|
register_chrome_path_provider_ = true;
|
|
}
|
|
}
|
|
|
|
// static
|
|
void ScopedChromeFrameRegistrar::RegisterAtPath(
|
|
const std::wstring& path, RegistrationType registration_type) {
|
|
|
|
ASSERT_FALSE(path.empty());
|
|
HMODULE dll_handle = LoadLibrary(path.c_str());
|
|
ASSERT_TRUE(dll_handle != NULL) << "Failed to load " << path
|
|
<< " , gle = " << GetLastError();
|
|
|
|
typedef HRESULT (STDAPICALLTYPE* DllRegisterServerFn)();
|
|
DllRegisterServerFn register_server = NULL;
|
|
|
|
if (registration_type == PER_USER) {
|
|
register_server = reinterpret_cast<DllRegisterServerFn>(GetProcAddress(
|
|
dll_handle, "DllRegisterUserServer"));
|
|
} else {
|
|
register_server = reinterpret_cast<DllRegisterServerFn>(GetProcAddress(
|
|
dll_handle, "DllRegisterServer"));
|
|
}
|
|
ASSERT_TRUE(register_server != NULL);
|
|
HRESULT reg_result = (*register_server)();
|
|
ASSERT_TRUE(FreeLibrary(dll_handle));
|
|
|
|
// Assert here after the FreeLibrary since otherwise we hit a
|
|
// multiple AtExitMananger crash for modules that use base.
|
|
ASSERT_HRESULT_SUCCEEDED(reg_result) << "Failed to register DLL at "
|
|
<< path
|
|
<< " , are you running as Admin?";
|
|
}
|
|
|
|
// static
|
|
void ScopedChromeFrameRegistrar::UnregisterAtPath(
|
|
const std::wstring& path, RegistrationType registration_type) {
|
|
|
|
ASSERT_FALSE(path.empty());
|
|
HMODULE dll_handle = LoadLibrary(path.c_str());
|
|
ASSERT_TRUE(dll_handle != NULL);
|
|
|
|
typedef HRESULT (STDAPICALLTYPE* DllUnregisterServerFn)();
|
|
DllUnregisterServerFn unregister_server = NULL;
|
|
if (registration_type == PER_USER) {
|
|
unregister_server = reinterpret_cast<DllUnregisterServerFn>
|
|
(GetProcAddress(dll_handle, "DllUnregisterUserServer"));
|
|
} else {
|
|
unregister_server = reinterpret_cast<DllUnregisterServerFn>
|
|
(GetProcAddress(dll_handle, "DllUnregisterServer"));
|
|
}
|
|
ASSERT_TRUE(unregister_server != NULL);
|
|
EXPECT_HRESULT_SUCCEEDED((*unregister_server)());
|
|
|
|
ASSERT_TRUE(FreeLibrary(dll_handle));
|
|
}
|
|
|
|
FilePath ScopedChromeFrameRegistrar::GetReferenceChromeFrameDllPath() {
|
|
FilePath reference_build_dir;
|
|
PathService::Get(chrome::DIR_APP, &reference_build_dir);
|
|
|
|
reference_build_dir = reference_build_dir.DirName();
|
|
reference_build_dir = reference_build_dir.DirName();
|
|
|
|
reference_build_dir = reference_build_dir.AppendASCII("chrome_frame");
|
|
reference_build_dir = reference_build_dir.AppendASCII("tools");
|
|
reference_build_dir = reference_build_dir.AppendASCII("test");
|
|
reference_build_dir = reference_build_dir.AppendASCII("reference_build");
|
|
reference_build_dir = reference_build_dir.AppendASCII("chrome");
|
|
reference_build_dir = reference_build_dir.AppendASCII("servers");
|
|
reference_build_dir = reference_build_dir.Append(kChromeFrameDllName);
|
|
return reference_build_dir;
|
|
}
|
|
|
|
// Non-statics
|
|
|
|
ScopedChromeFrameRegistrar::ScopedChromeFrameRegistrar(
|
|
const std::wstring& path, RegistrationType registration_type)
|
|
: registration_type_(registration_type) {
|
|
if (!register_chrome_path_provider_) {
|
|
// Register paths needed by the ScopedChromeFrameRegistrar.
|
|
chrome::RegisterPathProvider();
|
|
register_chrome_path_provider_ = true;
|
|
}
|
|
original_dll_path_ = path;
|
|
RegisterChromeFrameAtPath(original_dll_path_);
|
|
}
|
|
|
|
ScopedChromeFrameRegistrar::ScopedChromeFrameRegistrar(
|
|
RegistrationType registration_type)
|
|
: registration_type_(registration_type) {
|
|
if (!register_chrome_path_provider_) {
|
|
// Register paths needed by the ScopedChromeFrameRegistrar.
|
|
chrome::RegisterPathProvider();
|
|
register_chrome_path_provider_ = true;
|
|
}
|
|
original_dll_path_ = GetChromeFrameBuildPath().value();
|
|
RegisterChromeFrameAtPath(original_dll_path_);
|
|
}
|
|
|
|
ScopedChromeFrameRegistrar::~ScopedChromeFrameRegistrar() {
|
|
if (FilePath(original_dll_path_) != FilePath(new_chrome_frame_dll_path_)) {
|
|
RegisterChromeFrameAtPath(original_dll_path_);
|
|
} else if (registration_type_ == PER_USER) {
|
|
UnregisterAtPath(new_chrome_frame_dll_path_, registration_type_);
|
|
HWND chrome_frame_helper_window =
|
|
FindWindow(L"ChromeFrameHelperWindowClass", NULL);
|
|
if (IsWindow(chrome_frame_helper_window)) {
|
|
PostMessage(chrome_frame_helper_window, WM_CLOSE, 0, 0);
|
|
} else {
|
|
chrome_frame_test::KillProcesses(L"chrome_frame_helper.exe", 0, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ScopedChromeFrameRegistrar::RegisterChromeFrameAtPath(
|
|
const std::wstring& path) {
|
|
RegisterAtPath(path, registration_type_);
|
|
new_chrome_frame_dll_path_ = path;
|
|
}
|
|
|
|
void ScopedChromeFrameRegistrar::RegisterReferenceChromeFrameBuild() {
|
|
RegisterChromeFrameAtPath(GetReferenceChromeFrameDllPath().value());
|
|
}
|
|
|
|
std::wstring ScopedChromeFrameRegistrar::GetChromeFrameDllPath() const {
|
|
return new_chrome_frame_dll_path_;
|
|
}
|
|
|
|
// TODO(robertshield): The following could be factored out into its own file.
|
|
namespace {
|
|
|
|
typedef LONG WINAPI
|
|
NtQueryInformationProcess(
|
|
IN HANDLE ProcessHandle,
|
|
IN PROCESSINFOCLASS ProcessInformationClass,
|
|
OUT PVOID ProcessInformation,
|
|
IN ULONG ProcessInformationLength,
|
|
OUT PULONG ReturnLength OPTIONAL
|
|
);
|
|
|
|
// Get the function pointer to NtQueryInformationProcess in NTDLL.DLL
|
|
static bool GetQIP(NtQueryInformationProcess** qip_func_ptr) {
|
|
static NtQueryInformationProcess* qip_func =
|
|
reinterpret_cast<NtQueryInformationProcess*>(
|
|
GetProcAddress(GetModuleHandle(L"ntdll.dll"),
|
|
"NtQueryInformationProcess"));
|
|
DCHECK(qip_func) << "Could not get pointer to NtQueryInformationProcess.";
|
|
*qip_func_ptr = qip_func;
|
|
return qip_func != NULL;
|
|
}
|
|
|
|
// Get the command line of a process
|
|
bool GetCommandLineForProcess(uint32 process_id, std::wstring* cmd_line) {
|
|
DCHECK(process_id != 0);
|
|
DCHECK(cmd_line);
|
|
|
|
// Open the process
|
|
base::win::ScopedHandle process_handle(::OpenProcess(
|
|
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
|
|
false,
|
|
process_id));
|
|
if (!process_handle) {
|
|
DLOG(ERROR) << "Failed to open process " << process_id << ", last error = "
|
|
<< GetLastError();
|
|
}
|
|
|
|
// Obtain Process Environment Block
|
|
NtQueryInformationProcess* qip_func = NULL;
|
|
if (process_handle) {
|
|
GetQIP(&qip_func);
|
|
}
|
|
|
|
// Read the address of the process params from the peb.
|
|
DWORD process_params_address = 0;
|
|
if (qip_func) {
|
|
PROCESS_BASIC_INFORMATION info = { 0 };
|
|
// NtQueryInformationProcess returns an NTSTATUS for whom negative values
|
|
// are negative. Just check for that instead of pulling in DDK macros.
|
|
if ((qip_func(process_handle.Get(),
|
|
ProcessBasicInformation,
|
|
&info,
|
|
sizeof(info),
|
|
NULL)) < 0) {
|
|
DLOG(ERROR) << "Failed to invoke NtQueryProcessInformation, last error = "
|
|
<< GetLastError();
|
|
} else {
|
|
BYTE* peb = reinterpret_cast<BYTE*>(info.PebBaseAddress);
|
|
|
|
// The process command line parameters are (or were once) located at
|
|
// the base address of the PEB + 0x10 for 32 bit processes. 64 bit
|
|
// processes have a different PEB struct as per
|
|
// http://msdn.microsoft.com/en-us/library/aa813706(VS.85).aspx.
|
|
// TODO(robertshield): See about doing something about this.
|
|
SIZE_T bytes_read = 0;
|
|
if (!::ReadProcessMemory(process_handle.Get(),
|
|
peb + 0x10,
|
|
&process_params_address,
|
|
sizeof(process_params_address),
|
|
&bytes_read)) {
|
|
DLOG(ERROR) << "Failed to read process params address, last error = "
|
|
<< GetLastError();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Copy all the process parameters into a buffer.
|
|
bool success = false;
|
|
std::wstring buffer;
|
|
if (process_params_address) {
|
|
SIZE_T bytes_read;
|
|
RTL_USER_PROCESS_PARAMETERS params = { 0 };
|
|
if (!::ReadProcessMemory(process_handle.Get(),
|
|
reinterpret_cast<void*>(process_params_address),
|
|
¶ms,
|
|
sizeof(params),
|
|
&bytes_read)) {
|
|
DLOG(ERROR) << "Failed to read RTL_USER_PROCESS_PARAMETERS, "
|
|
<< "last error = " << GetLastError();
|
|
} else {
|
|
// Read the command line parameter
|
|
const int max_cmd_line_len = std::min(
|
|
static_cast<int>(params.CommandLine.MaximumLength),
|
|
4096);
|
|
buffer.resize(max_cmd_line_len + 1);
|
|
if (!::ReadProcessMemory(process_handle.Get(),
|
|
params.CommandLine.Buffer,
|
|
&buffer[0],
|
|
max_cmd_line_len,
|
|
&bytes_read)) {
|
|
DLOG(ERROR) << "Failed to copy process command line, "
|
|
<< "last error = " << GetLastError();
|
|
} else {
|
|
*cmd_line = buffer;
|
|
success = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
// Used to filter processes by process ID.
|
|
class ArgumentFilter : public base::ProcessFilter {
|
|
public:
|
|
explicit ArgumentFilter(const std::wstring& argument)
|
|
: argument_to_find_(argument) {}
|
|
|
|
// Returns true to indicate set-inclusion and false otherwise. This method
|
|
// should not have side-effects and should be idempotent.
|
|
virtual bool Includes(const base::ProcessEntry& entry) const {
|
|
bool found = false;
|
|
std::wstring command_line;
|
|
if (GetCommandLineForProcess(entry.pid(), &command_line)) {
|
|
std::wstring::const_iterator it =
|
|
std::search(command_line.begin(),
|
|
command_line.end(),
|
|
argument_to_find_.begin(),
|
|
argument_to_find_.end(),
|
|
base::CaseInsensitiveCompareASCII<wchar_t>());
|
|
found = (it != command_line.end());
|
|
}
|
|
return found;
|
|
}
|
|
|
|
protected:
|
|
std::wstring argument_to_find_;
|
|
};
|
|
|
|
} // namespace
|
|
|
|
bool KillAllNamedProcessesWithArgument(const std::wstring& process_name,
|
|
const std::wstring& argument) {
|
|
bool result = true;
|
|
ArgumentFilter filter(argument);
|
|
base::NamedProcessIterator iter(process_name, &filter);
|
|
while (const base::ProcessEntry* entry = iter.NextProcessEntry()) {
|
|
if (!base::KillProcessById(entry->pid(), 0, true)) {
|
|
result = false;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
bool IsWorkstationLocked() {
|
|
bool is_locked = true;
|
|
HDESK input_desk = ::OpenInputDesktop(0, 0, GENERIC_READ);
|
|
if (input_desk) {
|
|
wchar_t name[256] = {0};
|
|
DWORD needed = 0;
|
|
if (::GetUserObjectInformation(input_desk,
|
|
UOI_NAME,
|
|
name,
|
|
sizeof(name),
|
|
&needed)) {
|
|
is_locked = lstrcmpi(name, L"default") != 0;
|
|
}
|
|
::CloseDesktop(input_desk);
|
|
}
|
|
return is_locked;
|
|
}
|