Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(127)

Side by Side Diff: remoting/host/win/wts_session_process_delegate.cc

Issue 11118005: Pass the client end handle of the network-to-daemon IPC channel via handle inheritance. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: CR feedback. Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « remoting/host/win/wts_session_process_delegate.h ('k') | remoting/remoting.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 // 4 //
5 // This file implements the Windows service controlling Me2Me host processes 5 // This file implements the Windows service controlling Me2Me host processes
6 // running within user sessions. 6 // running within user sessions.
7 7
8 #include "remoting/host/win/wts_session_process_delegate.h" 8 #include "remoting/host/win/wts_session_process_delegate.h"
9 9
10 #include <sddl.h>
11 #include <limits>
12
13 #include "base/base_switches.h" 10 #include "base/base_switches.h"
14 #include "base/bind.h" 11 #include "base/bind.h"
15 #include "base/bind_helpers.h" 12 #include "base/bind_helpers.h"
16 #include "base/command_line.h" 13 #include "base/command_line.h"
17 #include "base/file_path.h" 14 #include "base/file_path.h"
18 #include "base/file_util.h" 15 #include "base/file_util.h"
19 #include "base/logging.h" 16 #include "base/logging.h"
20 #include "base/memory/scoped_ptr.h" 17 #include "base/memory/scoped_ptr.h"
21 #include "base/message_loop.h" 18 #include "base/message_loop.h"
22 #include "base/path_service.h"
23 #include "base/single_thread_task_runner.h" 19 #include "base/single_thread_task_runner.h"
24 #include "base/time.h"
25 #include "base/timer.h"
26 #include "base/utf_string_conversions.h" 20 #include "base/utf_string_conversions.h"
27 #include "base/win/scoped_handle.h" 21 #include "base/win/scoped_handle.h"
28 #include "base/win/windows_version.h" 22 #include "base/win/windows_version.h"
29 #include "ipc/ipc_channel.h" 23 #include "ipc/ipc_channel.h"
30 #include "ipc/ipc_channel_proxy.h" 24 #include "ipc/ipc_channel_proxy.h"
31 #include "ipc/ipc_message.h" 25 #include "ipc/ipc_message.h"
32 #include "remoting/host/host_exit_codes.h" 26 #include "remoting/host/host_exit_codes.h"
27 #include "remoting/host/ipc_consts.h"
33 #include "remoting/host/win/launch_process_with_token.h" 28 #include "remoting/host/win/launch_process_with_token.h"
34 #include "remoting/host/win/worker_process_launcher.h" 29 #include "remoting/host/win/worker_process_launcher.h"
35 #include "remoting/host/win/wts_console_monitor.h" 30 #include "remoting/host/win/wts_console_monitor.h"
36 #include "remoting/host/worker_process_ipc_delegate.h" 31 #include "remoting/host/worker_process_ipc_delegate.h"
37 32
38 using base::TimeDelta;
39 using base::win::ScopedHandle; 33 using base::win::ScopedHandle;
40 34
41 const FilePath::CharType kDaemonBinaryName[] =
42 FILE_PATH_LITERAL("remoting_daemon.exe");
43
44 // The command line switch specifying the name of the daemon IPC endpoint.
45 const char kDaemonIpcSwitchName[] = "daemon-pipe";
46
47 const char kElevateSwitchName[] = "elevate"; 35 const char kElevateSwitchName[] = "elevate";
48 36
49 // The command line parameters that should be copied from the service's command 37 // The command line parameters that should be copied from the service's command
50 // line to the host process. 38 // line to the host process.
51 const char* kCopiedSwitchNames[] = { 39 const char* kCopiedSwitchNames[] = {
52 "host-config", switches::kV, switches::kVModule }; 40 "host-config", switches::kV, switches::kVModule };
53 41
54 namespace remoting { 42 namespace remoting {
55 43
56 // A private class actually implementing the functionality provided by 44 // A private class actually implementing the functionality provided by
57 // |WtsSessionProcessDelegate|. This class is ref-counted and implements 45 // |WtsSessionProcessDelegate|. This class is ref-counted and implements
58 // asynchronous fire-and-forget shutdown. 46 // asynchronous fire-and-forget shutdown.
59 class WtsSessionProcessDelegate::Core 47 class WtsSessionProcessDelegate::Core
60 : public base::RefCountedThreadSafe<WtsSessionProcessDelegate::Core>, 48 : public base::RefCountedThreadSafe<WtsSessionProcessDelegate::Core>,
61 public base::MessagePumpForIO::IOHandler, 49 public base::MessagePumpForIO::IOHandler,
62 public WorkerProcessLauncher::Delegate { 50 public WorkerProcessLauncher::Delegate {
63 public: 51 public:
64 // The caller must ensure that |delegate| remains valid at least until 52 // The caller must ensure that |delegate| remains valid at least until
65 // Stop() method has been called. 53 // Stop() method has been called.
66 Core(scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, 54 Core(scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
67 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, 55 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
68 const FilePath& binary_path, 56 const FilePath& binary_path,
69 bool launch_elevated); 57 bool launch_elevated,
58 const std::string& channel_security);
70 59
71 // base::MessagePumpForIO::IOHandler implementation. 60 // base::MessagePumpForIO::IOHandler implementation.
72 virtual void OnIOCompleted(base::MessagePumpForIO::IOContext* context, 61 virtual void OnIOCompleted(base::MessagePumpForIO::IOContext* context,
73 DWORD bytes_transferred, 62 DWORD bytes_transferred,
74 DWORD error) OVERRIDE; 63 DWORD error) OVERRIDE;
75 64
65 // IPC::Sender implementation.
66 virtual bool Send(IPC::Message* message) OVERRIDE;
67
76 // WorkerProcessLauncher::Delegate implementation. 68 // WorkerProcessLauncher::Delegate implementation.
77 virtual DWORD GetExitCode() OVERRIDE; 69 virtual DWORD GetExitCode() OVERRIDE;
78 virtual void KillProcess(DWORD exit_code) OVERRIDE; 70 virtual void KillProcess(DWORD exit_code) OVERRIDE;
79 virtual bool LaunchProcess( 71 virtual bool LaunchProcess(
80 const std::string& channel_name, 72 IPC::Listener* delegate,
81 base::win::ScopedHandle* process_exit_event_out) OVERRIDE; 73 base::win::ScopedHandle* process_exit_event_out) OVERRIDE;
82 74
83 // Initializes the object returning true on success. 75 // Initializes the object returning true on success.
84 bool Initialize(uint32 session_id); 76 bool Initialize(uint32 session_id);
85 77
86 // Stops the object asynchronously. 78 // Stops the object asynchronously.
87 void Stop(); 79 void Stop();
88 80
89 private: 81 private:
90 friend class base::RefCountedThreadSafe<Core>; 82 friend class base::RefCountedThreadSafe<Core>;
(...skipping 18 matching lines...) Expand all
109 101
110 // The task runner all public methods of this class should be called on. 102 // The task runner all public methods of this class should be called on.
111 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; 103 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
112 104
113 // The task runner serving job object notifications. 105 // The task runner serving job object notifications.
114 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; 106 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
115 107
116 // Path to the worker process binary. 108 // Path to the worker process binary.
117 FilePath binary_path_; 109 FilePath binary_path_;
118 110
111 // The server end of the IPC channel used to communicate to the worker
112 // process.
113 scoped_ptr<IPC::ChannelProxy> channel_;
114
115 // Security descriptor (as SDDL) to be applied to |channel_|.
116 std::string channel_security_;
117
119 // The job object used to control the lifetime of child processes. 118 // The job object used to control the lifetime of child processes.
120 base::win::ScopedHandle job_; 119 base::win::ScopedHandle job_;
121 120
122 // True if the worker process should be launched elevated. 121 // True if the worker process should be launched elevated.
123 bool launch_elevated_; 122 bool launch_elevated_;
124 123
125 // A handle that becomes signalled once all processes associated with the job 124 // A handle that becomes signalled once all processes associated with the job
126 // have been terminated. 125 // have been terminated.
127 base::win::ScopedHandle process_exit_event_; 126 base::win::ScopedHandle process_exit_event_;
128 127
129 // The token to be used to launch a process in a different session. 128 // The token to be used to launch a process in a different session.
130 base::win::ScopedHandle session_token_; 129 base::win::ScopedHandle session_token_;
131 130
132 // True if Stop() has been called. 131 // True if Stop() has been called.
133 bool stopping_; 132 bool stopping_;
134 133
135 // The handle of the worker process, if launched. 134 // The handle of the worker process, if launched.
136 base::win::ScopedHandle worker_process_; 135 base::win::ScopedHandle worker_process_;
137 136
138 DISALLOW_COPY_AND_ASSIGN(Core); 137 DISALLOW_COPY_AND_ASSIGN(Core);
139 }; 138 };
140 139
141 WtsSessionProcessDelegate::Core::Core( 140 WtsSessionProcessDelegate::Core::Core(
142 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, 141 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
143 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, 142 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
144 const FilePath& binary_path, 143 const FilePath& binary_path,
145 bool launch_elevated) 144 bool launch_elevated,
145 const std::string& channel_security)
146 : main_task_runner_(main_task_runner), 146 : main_task_runner_(main_task_runner),
147 io_task_runner_(io_task_runner), 147 io_task_runner_(io_task_runner),
148 binary_path_(binary_path), 148 binary_path_(binary_path),
149 channel_security_(channel_security),
149 launch_elevated_(launch_elevated), 150 launch_elevated_(launch_elevated),
150 stopping_(false) { 151 stopping_(false) {
151 DCHECK(main_task_runner_->BelongsToCurrentThread()); 152 DCHECK(main_task_runner_->BelongsToCurrentThread());
152 } 153 }
153 154
154 void WtsSessionProcessDelegate::Core::OnIOCompleted( 155 void WtsSessionProcessDelegate::Core::OnIOCompleted(
155 base::MessagePumpForIO::IOContext* context, 156 base::MessagePumpForIO::IOContext* context,
156 DWORD bytes_transferred, 157 DWORD bytes_transferred,
157 DWORD error) { 158 DWORD error) {
158 DCHECK(io_task_runner_->BelongsToCurrentThread()); 159 DCHECK(io_task_runner_->BelongsToCurrentThread());
159 160
160 // |bytes_transferred| is used in job object notifications to supply 161 // |bytes_transferred| is used in job object notifications to supply
161 // the message ID; |context| carries process ID. 162 // the message ID; |context| carries process ID.
162 main_task_runner_->PostTask(FROM_HERE, base::Bind( 163 main_task_runner_->PostTask(FROM_HERE, base::Bind(
163 &Core::OnJobNotification, this, bytes_transferred, 164 &Core::OnJobNotification, this, bytes_transferred,
164 reinterpret_cast<DWORD>(context))); 165 reinterpret_cast<DWORD>(context)));
165 } 166 }
166 167
168 bool WtsSessionProcessDelegate::Core::Send(IPC::Message* message) {
169 DCHECK(main_task_runner_->BelongsToCurrentThread());
170
171 if (channel_.get()) {
172 return channel_->Send(message);
173 } else {
174 delete message;
175 return false;
176 }
177 }
178
167 DWORD WtsSessionProcessDelegate::Core::GetExitCode() { 179 DWORD WtsSessionProcessDelegate::Core::GetExitCode() {
168 DCHECK(main_task_runner_->BelongsToCurrentThread()); 180 DCHECK(main_task_runner_->BelongsToCurrentThread());
169 181
170 DWORD exit_code = CONTROL_C_EXIT; 182 DWORD exit_code = CONTROL_C_EXIT;
171 if (worker_process_.IsValid()) { 183 if (worker_process_.IsValid()) {
172 if (!::GetExitCodeProcess(worker_process_, &exit_code)) { 184 if (!::GetExitCodeProcess(worker_process_, &exit_code)) {
173 LOG_GETLASTERROR(INFO) 185 LOG_GETLASTERROR(INFO)
174 << "Failed to query the exit code of the worker process"; 186 << "Failed to query the exit code of the worker process";
175 exit_code = CONTROL_C_EXIT; 187 exit_code = CONTROL_C_EXIT;
176 } 188 }
177 } 189 }
178 190
179 return exit_code; 191 return exit_code;
180 } 192 }
181 193
182 void WtsSessionProcessDelegate::Core::KillProcess(DWORD exit_code) { 194 void WtsSessionProcessDelegate::Core::KillProcess(DWORD exit_code) {
183 DCHECK(main_task_runner_->BelongsToCurrentThread()); 195 DCHECK(main_task_runner_->BelongsToCurrentThread());
184 196
197 channel_.reset();
198
185 if (launch_elevated_) { 199 if (launch_elevated_) {
186 if (job_.IsValid()) { 200 if (job_.IsValid()) {
187 TerminateJobObject(job_, exit_code); 201 TerminateJobObject(job_, exit_code);
188 } 202 }
189 } else { 203 } else {
190 if (worker_process_.IsValid()) { 204 if (worker_process_.IsValid()) {
191 TerminateProcess(worker_process_, exit_code); 205 TerminateProcess(worker_process_, exit_code);
192 } 206 }
193 } 207 }
194 } 208 }
195 209
196 bool WtsSessionProcessDelegate::Core::LaunchProcess( 210 bool WtsSessionProcessDelegate::Core::LaunchProcess(
197 const std::string& channel_name, 211 IPC::Listener* delegate,
198 ScopedHandle* process_exit_event_out) { 212 ScopedHandle* process_exit_event_out) {
199 DCHECK(main_task_runner_->BelongsToCurrentThread()); 213 DCHECK(main_task_runner_->BelongsToCurrentThread());
200 214
201 CommandLine command_line(CommandLine::NO_PROGRAM); 215 CommandLine command_line(CommandLine::NO_PROGRAM);
202 if (launch_elevated_) { 216 if (launch_elevated_) {
203 // The job object is not ready. Retry starting the host process later. 217 // The job object is not ready. Retry starting the host process later.
204 if (!job_.IsValid()) { 218 if (!job_.IsValid()) {
205 return false; 219 return false;
206 } 220 }
207 221
208 // Construct the helper binary name. 222 // Construct the helper binary name.
209 FilePath dir_path; 223 FilePath daemon_binary;
210 if (!PathService::Get(base::DIR_EXE, &dir_path)) { 224 if (!GetInstalledBinaryPath(kDaemonBinaryName, &daemon_binary))
211 LOG(ERROR) << "Failed to get the executable file name.";
212 return false; 225 return false;
213 }
214 FilePath daemon_binary = dir_path.Append(kDaemonBinaryName);
215 226
216 // Create the command line passing the name of the IPC channel to use and 227 // Create the command line passing the name of the IPC channel to use and
217 // copying known switches from the caller's command line. 228 // copying known switches from the caller's command line.
218 command_line.SetProgram(daemon_binary); 229 command_line.SetProgram(daemon_binary);
219 command_line.AppendSwitchPath(kElevateSwitchName, binary_path_); 230 command_line.AppendSwitchPath(kElevateSwitchName, binary_path_);
220 231
221 CHECK(ResetEvent(process_exit_event_)); 232 CHECK(ResetEvent(process_exit_event_));
222 } else { 233 } else {
223 command_line.SetProgram(binary_path_); 234 command_line.SetProgram(binary_path_);
224 } 235 }
225 236
237 // Create the server end of the IPC channel.
238 scoped_ptr<IPC::ChannelProxy> channel;
239 std::string channel_name = GenerateIpcChannelName(this);
240 if (!CreateIpcChannel(channel_name, channel_security_, io_task_runner_,
241 delegate, &channel))
242 return false;
243
226 // Create the command line passing the name of the IPC channel to use and 244 // Create the command line passing the name of the IPC channel to use and
227 // copying known switches from the caller's command line. 245 // copying known switches from the caller's command line.
228 command_line.AppendSwitchNative(kDaemonIpcSwitchName, 246 command_line.AppendSwitchNative(kDaemonPipeSwitchName,
229 UTF8ToWide(channel_name)); 247 UTF8ToWide(channel_name));
230 command_line.CopySwitchesFrom(*CommandLine::ForCurrentProcess(), 248 command_line.CopySwitchesFrom(*CommandLine::ForCurrentProcess(),
231 kCopiedSwitchNames, 249 kCopiedSwitchNames,
232 arraysize(kCopiedSwitchNames)); 250 arraysize(kCopiedSwitchNames));
233 251
234 // Try to launch the process. 252 // Try to launch the process.
235 ScopedHandle worker_process; 253 ScopedHandle worker_process;
236 ScopedHandle worker_thread; 254 ScopedHandle worker_thread;
237 if (!LaunchProcessWithToken(command_line.GetProgram(), 255 if (!LaunchProcessWithToken(command_line.GetProgram(),
238 command_line.GetCommandLineString(), 256 command_line.GetCommandLineString(),
239 session_token_, 257 session_token_,
258 false,
240 CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB, 259 CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB,
241 &worker_process, 260 &worker_process,
242 &worker_thread)) { 261 &worker_thread)) {
243 return false; 262 return false;
244 } 263 }
245 264
246 HANDLE local_process_exit_event; 265 HANDLE local_process_exit_event;
247 if (launch_elevated_) { 266 if (launch_elevated_) {
248 if (!AssignProcessToJobObject(job_, worker_process)) { 267 if (!AssignProcessToJobObject(job_, worker_process)) {
249 LOG_GETLASTERROR(ERROR) 268 LOG_GETLASTERROR(ERROR)
(...skipping 22 matching lines...) Expand all
272 GetCurrentProcess(), 291 GetCurrentProcess(),
273 process_exit_event.Receive(), 292 process_exit_event.Receive(),
274 SYNCHRONIZE, 293 SYNCHRONIZE,
275 FALSE, 294 FALSE,
276 0)) { 295 0)) {
277 LOG_GETLASTERROR(ERROR) << "Failed to duplicate a handle"; 296 LOG_GETLASTERROR(ERROR) << "Failed to duplicate a handle";
278 KillProcess(CONTROL_C_EXIT); 297 KillProcess(CONTROL_C_EXIT);
279 return false; 298 return false;
280 } 299 }
281 300
301 channel_ = channel.Pass();
282 *process_exit_event_out = process_exit_event.Pass(); 302 *process_exit_event_out = process_exit_event.Pass();
283 return true; 303 return true;
284 } 304 }
285 305
286 bool WtsSessionProcessDelegate::Core::Initialize(uint32 session_id) { 306 bool WtsSessionProcessDelegate::Core::Initialize(uint32 session_id) {
287 if (base::win::GetVersion() == base::win::VERSION_XP) 307 if (base::win::GetVersion() == base::win::VERSION_XP)
288 launch_elevated_ = false; 308 launch_elevated_ = false;
289 309
290 if (launch_elevated_) { 310 if (launch_elevated_) {
291 process_exit_event_.Set(CreateEvent(NULL, TRUE, FALSE, NULL)); 311 process_exit_event_.Set(CreateEvent(NULL, TRUE, FALSE, NULL));
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 worker_process_.Set(OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid)); 432 worker_process_.Set(OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid));
413 break; 433 break;
414 } 434 }
415 } 435 }
416 436
417 WtsSessionProcessDelegate::WtsSessionProcessDelegate( 437 WtsSessionProcessDelegate::WtsSessionProcessDelegate(
418 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, 438 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
419 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, 439 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
420 const FilePath& binary_path, 440 const FilePath& binary_path,
421 uint32 session_id, 441 uint32 session_id,
422 bool launch_elevated) { 442 bool launch_elevated,
443 const std::string& channel_security) {
423 core_ = new Core(main_task_runner, io_task_runner, binary_path, 444 core_ = new Core(main_task_runner, io_task_runner, binary_path,
424 launch_elevated); 445 launch_elevated, channel_security);
425 if (!core_->Initialize(session_id)) { 446 if (!core_->Initialize(session_id)) {
426 core_->Stop(); 447 core_->Stop();
427 core_ = NULL; 448 core_ = NULL;
428 } 449 }
429 } 450 }
430 451
431 WtsSessionProcessDelegate::~WtsSessionProcessDelegate() { 452 WtsSessionProcessDelegate::~WtsSessionProcessDelegate() {
432 core_->Stop(); 453 core_->Stop();
433 } 454 }
434 455
456 bool WtsSessionProcessDelegate::Send(IPC::Message* message) {
457 return core_->Send(message);
458 }
459
435 DWORD WtsSessionProcessDelegate::GetExitCode() { 460 DWORD WtsSessionProcessDelegate::GetExitCode() {
436 if (!core_) 461 if (!core_)
437 return CONTROL_C_EXIT; 462 return CONTROL_C_EXIT;
438 463
439 return core_->GetExitCode(); 464 return core_->GetExitCode();
440 } 465 }
441 466
442 void WtsSessionProcessDelegate::KillProcess(DWORD exit_code) { 467 void WtsSessionProcessDelegate::KillProcess(DWORD exit_code) {
443 if (core_) { 468 if (core_) {
444 core_->KillProcess(exit_code); 469 core_->KillProcess(exit_code);
445 } 470 }
446 } 471 }
447 472
448 bool WtsSessionProcessDelegate::LaunchProcess( 473 bool WtsSessionProcessDelegate::LaunchProcess(
449 const std::string& channel_name, 474 IPC::Listener* delegate,
450 base::win::ScopedHandle* process_exit_event_out) { 475 base::win::ScopedHandle* process_exit_event_out) {
451 if (!core_) 476 if (!core_)
452 return false; 477 return false;
453 478
454 return core_->LaunchProcess(channel_name, process_exit_event_out); 479 return core_->LaunchProcess(delegate, process_exit_event_out);
455 } 480 }
456 481
457 } // namespace remoting 482 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/win/wts_session_process_delegate.h ('k') | remoting/remoting.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698