| Index: remoting/host/win/unprivileged_process_delegate.cc
|
| diff --git a/remoting/host/win/unprivileged_process_delegate.cc b/remoting/host/win/unprivileged_process_delegate.cc
|
| index 74d539dec0f1408d9e4df0b23bd877bebcd57ca0..890e63fe1d0187a60861c7d757955bc11af834c9 100644
|
| --- a/remoting/host/win/unprivileged_process_delegate.cc
|
| +++ b/remoting/host/win/unprivileged_process_delegate.cc
|
| @@ -11,16 +11,23 @@
|
| #include "base/command_line.h"
|
| #include "base/logging.h"
|
| #include "base/single_thread_task_runner.h"
|
| +#include "base/stringprintf.h"
|
| #include "base/utf_string_conversions.h"
|
| #include "base/win/scoped_handle.h"
|
| +#include "ipc/ipc_channel_proxy.h"
|
| +#include "ipc/ipc_message.h"
|
| +#include "remoting/host/ipc_consts.h"
|
| #include "remoting/host/win/launch_process_with_token.h"
|
|
|
| using base::win::ScopedHandle;
|
|
|
| namespace {
|
|
|
| -// The command line switch specifying the name of the daemon IPC endpoint.
|
| -const char kDaemonIpcSwitchName[] = "daemon-pipe";
|
| +// The security descriptor used to protect the named pipe in between
|
| +// CreateNamedPipe() and CreateFile() calls before it will be passed to
|
| +// the network process. It gives full access to LocalSystem and denies access by
|
| +// anyone else.
|
| +const char kDaemonIpcSecurityDescriptor[] = "O:SYG:SYD:(A;;GA;;;SY)";
|
|
|
| // The command line parameters that should be copied from the service's command
|
| // line to the host process.
|
| @@ -44,6 +51,12 @@ UnprivilegedProcessDelegate::~UnprivilegedProcessDelegate() {
|
| KillProcess(CONTROL_C_EXIT);
|
| }
|
|
|
| +bool UnprivilegedProcessDelegate::Send(IPC::Message* message) {
|
| + DCHECK(main_task_runner_->BelongsToCurrentThread());
|
| +
|
| + return channel_->Send(message);
|
| +}
|
| +
|
| DWORD UnprivilegedProcessDelegate::GetExitCode() {
|
| DCHECK(main_task_runner_->BelongsToCurrentThread());
|
|
|
| @@ -62,21 +75,35 @@ DWORD UnprivilegedProcessDelegate::GetExitCode() {
|
| void UnprivilegedProcessDelegate::KillProcess(DWORD exit_code) {
|
| DCHECK(main_task_runner_->BelongsToCurrentThread());
|
|
|
| + channel_.reset();
|
| +
|
| if (worker_process_.IsValid()) {
|
| TerminateProcess(worker_process_, exit_code);
|
| }
|
| }
|
|
|
| bool UnprivilegedProcessDelegate::LaunchProcess(
|
| - const std::string& channel_name,
|
| + IPC::Listener* delegate,
|
| ScopedHandle* process_exit_event_out) {
|
| DCHECK(main_task_runner_->BelongsToCurrentThread());
|
| + // Generate a unique name for the channel.
|
| + std::string channel_name = GenerateIpcChannelName(this);
|
| +
|
| + // Create a connected IPC channel.
|
| + ScopedHandle client;
|
| + scoped_ptr<IPC::ChannelProxy> server;
|
| + if (!CreateConnectedIpcChannel(channel_name, delegate, &client, &server))
|
| + return false;
|
| +
|
| + // Convert the handle value into a decimal integer. Handle values are 32bit
|
| + // even on 64bit platforms.
|
| + std::string pipe_handle = base::StringPrintf(
|
| + "%d", reinterpret_cast<ULONG_PTR>(client.Get()));
|
|
|
| // Create the command line passing the name of the IPC channel to use and
|
| // copying known switches from the caller's command line.
|
| CommandLine command_line(binary_path_);
|
| - command_line.AppendSwitchNative(kDaemonIpcSwitchName,
|
| - UTF8ToWide(channel_name));
|
| + command_line.AppendSwitchASCII(kDaemonPipeSwitchName, pipe_handle);
|
| command_line.CopySwitchesFrom(*CommandLine::ForCurrentProcess(),
|
| kCopiedSwitchNames,
|
| arraysize(kCopiedSwitchNames));
|
| @@ -89,6 +116,7 @@ bool UnprivilegedProcessDelegate::LaunchProcess(
|
| if (!LaunchProcessWithToken(command_line.GetProgram(),
|
| command_line.GetCommandLineString(),
|
| NULL,
|
| + true,
|
| 0,
|
| &worker_process_,
|
| &worker_thread)) {
|
| @@ -110,8 +138,49 @@ bool UnprivilegedProcessDelegate::LaunchProcess(
|
| return false;
|
| }
|
|
|
| + channel_ = server.Pass();
|
| *process_exit_event_out = process_exit_event.Pass();
|
| return true;
|
| }
|
|
|
| +bool UnprivilegedProcessDelegate::CreateConnectedIpcChannel(
|
| + const std::string& channel_name,
|
| + IPC::Listener* delegate,
|
| + ScopedHandle* client_out,
|
| + scoped_ptr<IPC::ChannelProxy>* server_out) {
|
| + // Create the server end of the channel.
|
| + scoped_ptr<IPC::ChannelProxy> server;
|
| + if (!CreateIpcChannel(channel_name, kDaemonIpcSecurityDescriptor,
|
| + io_task_runner_, delegate, &server)) {
|
| + return false;
|
| + }
|
| +
|
| + // Convert the channel name to the pipe name.
|
| + std::string pipe_name(kChromePipeNamePrefix);
|
| + pipe_name.append(channel_name);
|
| +
|
| + SECURITY_ATTRIBUTES security_attributes;
|
| + security_attributes.nLength = sizeof(security_attributes);
|
| + security_attributes.lpSecurityDescriptor = NULL;
|
| + security_attributes.bInheritHandle = TRUE;
|
| +
|
| + // Create the client end of the channel. This code should match the code in
|
| + // IPC::Channel.
|
| + ScopedHandle client;
|
| + client.Set(CreateFile(UTF8ToUTF16(pipe_name).c_str(),
|
| + GENERIC_READ | GENERIC_WRITE,
|
| + 0,
|
| + &security_attributes,
|
| + OPEN_EXISTING,
|
| + SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION |
|
| + FILE_FLAG_OVERLAPPED,
|
| + NULL));
|
| + if (!client.IsValid())
|
| + return false;
|
| +
|
| + *client_out = client.Pass();
|
| + *server_out = server.Pass();
|
| + return true;
|
| +}
|
| +
|
| } // namespace remoting
|
|
|