This source file includes following definitions.
- IsProcessElevated
- StartMe2MeNativeMessagingHost
- Me2MeNativeMessagingHostMain
#include "remoting/host/setup/me2me_native_messaging_host_main.h"
#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "net/url_request/url_fetcher.h"
#include "remoting/base/breakpad.h"
#include "remoting/host/host_exit_codes.h"
#include "remoting/host/logging.h"
#include "remoting/host/pairing_registry_delegate.h"
#include "remoting/host/setup/me2me_native_messaging_host.h"
#include "remoting/host/usage_stats_consent.h"
#if defined(OS_MACOSX)
#include "base/mac/scoped_nsautorelease_pool.h"
#endif
#if defined(OS_WIN)
#include "base/win/registry.h"
#include "base/win/windows_version.h"
#include "remoting/host/pairing_registry_delegate_win.h"
#endif
using remoting::protocol::PairingRegistry;
namespace {
const char kParentWindowSwitchName[] = "parent-window";
}
namespace remoting {
#if defined(OS_WIN)
bool IsProcessElevated() {
if (base::win::GetVersion() < base::win::VERSION_VISTA)
return true;
HANDLE process_token;
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &process_token);
base::win::ScopedHandle scoped_process_token(process_token);
DWORD size;
TOKEN_ELEVATION elevation;
GetTokenInformation(process_token, TokenElevation,
&elevation, sizeof(elevation), &size);
return elevation.TokenIsElevated != 0;
}
#endif
int StartMe2MeNativeMessagingHost() {
#if defined(OS_MACOSX)
base::mac::ScopedNSAutoreleasePool pool;
#endif
#if defined(REMOTING_ENABLE_BREAKPAD)
if (IsUsageStatsAllowed()) {
InitializeCrashReporting();
}
#endif
base::Thread io_thread("io_thread");
io_thread.StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
base::MessageLoopForUI message_loop;
base::RunLoop run_loop;
scoped_refptr<DaemonController> daemon_controller =
DaemonController::Create();
const CommandLine* command_line = CommandLine::ForCurrentProcess();
int64 native_view_handle = 0;
if (command_line->HasSwitch(kParentWindowSwitchName)) {
std::string native_view =
command_line->GetSwitchValueASCII(kParentWindowSwitchName);
if (base::StringToInt64(native_view, &native_view_handle)) {
daemon_controller->SetWindow(reinterpret_cast<void*>(native_view_handle));
} else {
LOG(WARNING) << "Invalid parameter value --" << kParentWindowSwitchName
<< "=" << native_view;
}
}
base::PlatformFile read_file;
base::PlatformFile write_file;
bool needs_elevation = false;
#if defined(OS_WIN)
needs_elevation = !IsProcessElevated();
if (command_line->HasSwitch(kElevatingSwitchName)) {
DCHECK(!needs_elevation);
DCHECK(command_line->HasSwitch(kInputSwitchName));
DCHECK(command_line->HasSwitch(kOutputSwitchName));
std::wstring input_pipe_name =
command_line->GetSwitchValueNative(kInputSwitchName);
std::wstring output_pipe_name =
command_line->GetSwitchValueNative(kOutputSwitchName);
read_file = CreateFile(
input_pipe_name.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if (read_file == INVALID_HANDLE_VALUE) {
LOG_GETLASTERROR(ERROR) <<
"CreateFile failed on '" << input_pipe_name << "'";
return kInitializationFailed;
}
write_file = CreateFile(
output_pipe_name.c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if (write_file == INVALID_HANDLE_VALUE) {
LOG_GETLASTERROR(ERROR) <<
"CreateFile failed on '" << output_pipe_name << "'";
return kInitializationFailed;
}
} else {
read_file = GetStdHandle(STD_INPUT_HANDLE);
write_file = GetStdHandle(STD_OUTPUT_HANDLE);
SetStdHandle(STD_INPUT_HANDLE, NULL);
SetStdHandle(STD_OUTPUT_HANDLE, NULL);
}
#elif defined(OS_POSIX)
read_file = STDIN_FILENO;
write_file = STDOUT_FILENO;
#else
#error Not implemented.
#endif
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter(
new URLRequestContextGetter(io_thread.message_loop_proxy()));
scoped_ptr<OAuthClient> oauth_client(
new OAuthClient(url_request_context_getter));
net::URLFetcher::SetIgnoreCertificateRequests(true);
scoped_refptr<PairingRegistry> pairing_registry;
#if defined(OS_WIN)
base::win::RegKey root;
LONG result = root.Open(HKEY_LOCAL_MACHINE, kPairingRegistryKeyName,
KEY_READ);
if (result != ERROR_SUCCESS) {
SetLastError(result);
PLOG(ERROR) << "Failed to open HKLM\\" << kPairingRegistryKeyName;
return kInitializationFailed;
}
base::win::RegKey unprivileged;
result = unprivileged.Open(root.Handle(), kPairingRegistrySecretsKeyName,
needs_elevation ? KEY_READ : KEY_READ | KEY_WRITE);
if (result != ERROR_SUCCESS) {
SetLastError(result);
PLOG(ERROR) << "Failed to open HKLM\\" << kPairingRegistrySecretsKeyName
<< "\\" << kPairingRegistrySecretsKeyName;
return kInitializationFailed;
}
base::win::RegKey privileged;
if (!needs_elevation) {
result = privileged.Open(root.Handle(), kPairingRegistryClientsKeyName,
KEY_READ | KEY_WRITE);
if (result != ERROR_SUCCESS) {
SetLastError(result);
PLOG(ERROR) << "Failed to open HKLM\\" << kPairingRegistryKeyName << "\\"
<< kPairingRegistryClientsKeyName;
return kInitializationFailed;
}
}
scoped_ptr<PairingRegistryDelegateWin> delegate(
new PairingRegistryDelegateWin());
if (!delegate->SetRootKeys(privileged.Take(), unprivileged.Take()))
return kInitializationFailed;
pairing_registry = new PairingRegistry(
io_thread.message_loop_proxy(),
delegate.PassAs<PairingRegistry::Delegate>());
#else
pairing_registry =
CreatePairingRegistry(io_thread.message_loop_proxy());
#endif
scoped_ptr<NativeMessagingChannel> channel(
new NativeMessagingChannel(read_file, write_file));
scoped_ptr<Me2MeNativeMessagingHost> host(
new Me2MeNativeMessagingHost(
needs_elevation,
static_cast<intptr_t>(native_view_handle),
channel.Pass(),
daemon_controller,
pairing_registry,
oauth_client.Pass()));
host->Start(run_loop.QuitClosure());
run_loop.Run();
return kSuccessExitCode;
}
int Me2MeNativeMessagingHostMain(int argc, char** argv) {
base::AtExitManager exit_manager;
CommandLine::Init(argc, argv);
remoting::InitHostLogging();
return StartMe2MeNativeMessagingHost();
}
}