| OLD | NEW |
| 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_launcher.h" | 8 #include "remoting/host/win/wts_session_process_launcher.h" |
| 9 | 9 |
| 10 #include <windows.h> | 10 #include <windows.h> |
| 11 #include <sddl.h> | 11 #include <sddl.h> |
| 12 #include <limits> | 12 #include <limits> |
| 13 | 13 |
| 14 #include "base/base_switches.h" | 14 #include "base/base_switches.h" |
| 15 #include "base/bind.h" | 15 #include "base/bind.h" |
| 16 #include "base/bind_helpers.h" | 16 #include "base/bind_helpers.h" |
| 17 #include "base/command_line.h" | 17 #include "base/command_line.h" |
| 18 #include "base/file_path.h" | 18 #include "base/file_path.h" |
| 19 #include "base/file_util.h" | 19 #include "base/file_util.h" |
| 20 #include "base/logging.h" | 20 #include "base/logging.h" |
| 21 #include "base/single_thread_task_runner.h" | 21 #include "base/single_thread_task_runner.h" |
| 22 #include "base/path_service.h" | 22 #include "base/path_service.h" |
| 23 #include "base/process_util.h" | |
| 24 #include "base/rand_util.h" | 23 #include "base/rand_util.h" |
| 25 #include "base/stringprintf.h" | 24 #include "base/stringprintf.h" |
| 26 #include "base/utf_string_conversions.h" | 25 #include "base/utf_string_conversions.h" |
| 27 #include "base/win/scoped_handle.h" | 26 #include "base/win/scoped_handle.h" |
| 28 #include "ipc/ipc_channel_proxy.h" | 27 #include "ipc/ipc_channel_proxy.h" |
| 29 #include "ipc/ipc_message.h" | 28 #include "ipc/ipc_message.h" |
| 30 #include "ipc/ipc_message_macros.h" | 29 #include "ipc/ipc_message_macros.h" |
| 31 #include "remoting/host/constants.h" | 30 #include "remoting/host/constants.h" |
| 32 #include "remoting/host/chromoting_messages.h" | 31 #include "remoting/host/chromoting_messages.h" |
| 33 #include "remoting/host/win/launch_process_with_token.h" | 32 #include "remoting/host/win/launch_process_with_token.h" |
| 34 #include "remoting/host/win/wts_console_monitor.h" | 33 #include "remoting/host/win/wts_console_monitor.h" |
| 35 | 34 |
| 36 using base::win::ScopedHandle; | 35 using base::win::ScopedHandle; |
| 37 using base::TimeDelta; | 36 using base::TimeDelta; |
| 38 | 37 |
| 39 namespace { | 38 namespace { |
| 40 | 39 |
| 41 // The minimum and maximum delays between attempts to inject host process into | 40 // The minimum and maximum delays between attempts to inject host process into |
| 42 // a session. | 41 // a session. |
| 43 const int kMaxLaunchDelaySeconds = 60; | 42 const int kMaxLaunchDelaySeconds = 60; |
| 44 const int kMinLaunchDelaySeconds = 1; | 43 const int kMinLaunchDelaySeconds = 1; |
| 45 | 44 |
| 46 const FilePath::CharType kMe2meHostBinaryName[] = | 45 const FilePath::CharType kMe2meHostBinaryName[] = |
| 47 FILE_PATH_LITERAL("remoting_me2me_host.exe"); | 46 FILE_PATH_LITERAL("remoting_me2me_host.exe"); |
| 48 | 47 |
| 49 const FilePath::CharType kMe2meServiceBinaryName[] = | 48 const FilePath::CharType kMe2meServiceBinaryName[] = |
| 50 FILE_PATH_LITERAL("remoting_service.exe"); | 49 FILE_PATH_LITERAL("remoting_service.exe"); |
| 51 | 50 |
| 52 // The IPC channel name is passed to the host in the command line. | 51 // The command line switch specifying the name of the daemon IPC endpoint. |
| 53 const char kChromotingIpcSwitchName[] = "chromoting-ipc"; | 52 const char kDaemonIpcSwitchName[] = "daemon-pipe"; |
| 54 | 53 |
| 55 const char kElevateSwitchName[] = "elevate"; | 54 const char kElevateSwitchName[] = "elevate"; |
| 56 | 55 |
| 57 // The command line parameters that should be copied from the service's command | 56 // The command line parameters that should be copied from the service's command |
| 58 // line to the host process. | 57 // line to the host process. |
| 59 const char* kCopiedSwitchNames[] = { | 58 const char* kCopiedSwitchNames[] = { |
| 60 "auth-config", "host-config", switches::kV, switches::kVModule }; | 59 "host-config", switches::kV, switches::kVModule }; |
| 61 | 60 |
| 62 // The security descriptor of the Chromoting IPC channel. It gives full access | 61 // The security descriptor of the daemon IPC endpoint. It gives full access |
| 63 // to LocalSystem and denies access by anyone else. | 62 // to LocalSystem and denies access by anyone else. |
| 64 const char kChromotingChannelSecurityDescriptor[] = "O:SYG:SYD:(A;;GA;;;SY)"; | 63 const char kDaemonIpcSecurityDescriptor[] = "O:SYG:SYD:(A;;GA;;;SY)"; |
| 65 | 64 |
| 66 } // namespace | 65 } // namespace |
| 67 | 66 |
| 68 namespace remoting { | 67 namespace remoting { |
| 69 | 68 |
| 70 WtsSessionProcessLauncher::WtsSessionProcessLauncher( | 69 WtsSessionProcessLauncher::WtsSessionProcessLauncher( |
| 71 const base::Closure& stopped_callback, | 70 const base::Closure& stopped_callback, |
| 72 WtsConsoleMonitor* monitor, | 71 WtsConsoleMonitor* monitor, |
| 73 scoped_refptr<base::SingleThreadTaskRunner> main_message_loop, | 72 scoped_refptr<base::SingleThreadTaskRunner> main_message_loop, |
| 74 scoped_refptr<base::SingleThreadTaskRunner> ipc_message_loop) | 73 scoped_refptr<base::SingleThreadTaskRunner> ipc_message_loop) |
| (...skipping 12 matching lines...) Expand all Loading... |
| 87 // port represented by |ipc_message_loop|. The registration has to be done on | 86 // port represented by |ipc_message_loop|. The registration has to be done on |
| 88 // the I/O thread because MessageLoopForIO::RegisterJobObject() can only be | 87 // the I/O thread because MessageLoopForIO::RegisterJobObject() can only be |
| 89 // called via MessageLoopForIO::current(). | 88 // called via MessageLoopForIO::current(). |
| 90 ipc_message_loop_->PostTask(FROM_HERE, base::Bind( | 89 ipc_message_loop_->PostTask(FROM_HERE, base::Bind( |
| 91 &WtsSessionProcessLauncher::InitializeJob, | 90 &WtsSessionProcessLauncher::InitializeJob, |
| 92 base::Unretained(this))); | 91 base::Unretained(this))); |
| 93 } | 92 } |
| 94 | 93 |
| 95 WtsSessionProcessLauncher::~WtsSessionProcessLauncher() { | 94 WtsSessionProcessLauncher::~WtsSessionProcessLauncher() { |
| 96 // Make sure that the object is completely stopped. The same check exists | 95 // Make sure that the object is completely stopped. The same check exists |
| 97 // in Stoppable::~Stoppable() but this one allows us to examine the state of | 96 // in Stoppable::~Stoppable() but this one helps us to fail early and |
| 98 // the object before destruction. | 97 // predictably. |
| 99 CHECK_EQ(stoppable_state(), Stoppable::kStopped); | 98 CHECK_EQ(stoppable_state(), Stoppable::kStopped); |
| 100 | 99 |
| 101 monitor_->RemoveWtsConsoleObserver(this); | 100 monitor_->RemoveWtsConsoleObserver(this); |
| 102 | 101 |
| 103 CHECK(!attached_); | 102 CHECK(!attached_); |
| 104 CHECK(!timer_.IsRunning()); | 103 CHECK(!timer_.IsRunning()); |
| 105 } | 104 } |
| 106 | 105 |
| 107 void WtsSessionProcessLauncher::OnIOCompleted( | 106 void WtsSessionProcessLauncher::OnIOCompleted( |
| 108 base::MessagePumpForIO::IOContext* context, | 107 base::MessagePumpForIO::IOContext* context, |
| (...skipping 25 matching lines...) Expand all Loading... |
| 134 LOG(ERROR) << "Failed to get the executable file name."; | 133 LOG(ERROR) << "Failed to get the executable file name."; |
| 135 return false; | 134 return false; |
| 136 } | 135 } |
| 137 FilePath host_binary = dir_path.Append(kMe2meHostBinaryName); | 136 FilePath host_binary = dir_path.Append(kMe2meHostBinaryName); |
| 138 FilePath service_binary = dir_path.Append(kMe2meServiceBinaryName); | 137 FilePath service_binary = dir_path.Append(kMe2meServiceBinaryName); |
| 139 | 138 |
| 140 // Create the host process command line passing the name of the IPC channel | 139 // Create the host process command line passing the name of the IPC channel |
| 141 // to use and copying known switches from the service's command line. | 140 // to use and copying known switches from the service's command line. |
| 142 CommandLine command_line(service_binary); | 141 CommandLine command_line(service_binary); |
| 143 command_line.AppendSwitchPath(kElevateSwitchName, host_binary); | 142 command_line.AppendSwitchPath(kElevateSwitchName, host_binary); |
| 144 command_line.AppendSwitchNative(kChromotingIpcSwitchName, | 143 command_line.AppendSwitchNative(kDaemonIpcSwitchName, |
| 145 UTF8ToWide(channel_name)); | 144 UTF8ToWide(channel_name)); |
| 146 command_line.CopySwitchesFrom(*CommandLine::ForCurrentProcess(), | 145 command_line.CopySwitchesFrom(*CommandLine::ForCurrentProcess(), |
| 147 kCopiedSwitchNames, | 146 kCopiedSwitchNames, |
| 148 _countof(kCopiedSwitchNames)); | 147 _countof(kCopiedSwitchNames)); |
| 149 | 148 |
| 150 CHECK(ResetEvent(process_exit_event_)); | 149 CHECK(ResetEvent(process_exit_event_)); |
| 151 | 150 |
| 152 // Try to launch the process and attach an object watcher to the returned | 151 // Try to launch the process and attach an object watcher to the returned |
| 153 // handle so that we get notified when the process terminates. | 152 // handle so that we get notified when the process terminates. |
| 154 base::win::ScopedHandle worker_process; | 153 base::win::ScopedHandle worker_process; |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 368 } | 367 } |
| 369 | 368 |
| 370 void WtsSessionProcessLauncher::LaunchProcess() { | 369 void WtsSessionProcessLauncher::LaunchProcess() { |
| 371 DCHECK(main_message_loop_->BelongsToCurrentThread()); | 370 DCHECK(main_message_loop_->BelongsToCurrentThread()); |
| 372 DCHECK(attached_); | 371 DCHECK(attached_); |
| 373 DCHECK(launcher_.get() == NULL); | 372 DCHECK(launcher_.get() == NULL); |
| 374 DCHECK(!timer_.IsRunning()); | 373 DCHECK(!timer_.IsRunning()); |
| 375 | 374 |
| 376 launch_time_ = base::Time::Now(); | 375 launch_time_ = base::Time::Now(); |
| 377 launcher_.reset(new WorkerProcessLauncher( | 376 launcher_.reset(new WorkerProcessLauncher( |
| 378 this, | 377 this, this, |
| 379 base::Bind(&WtsSessionProcessLauncher::OnLauncherStopped, | 378 base::Bind(&WtsSessionProcessLauncher::OnLauncherStopped, |
| 380 base::Unretained(this)), | 379 base::Unretained(this)), |
| 381 main_message_loop_, | 380 main_message_loop_, |
| 382 ipc_message_loop_)); | 381 ipc_message_loop_)); |
| 383 launcher_->Start(kChromotingChannelSecurityDescriptor); | 382 launcher_->Start(kDaemonIpcSecurityDescriptor); |
| 384 } | 383 } |
| 385 | 384 |
| 386 void WtsSessionProcessLauncher::OnLauncherStopped() { | 385 void WtsSessionProcessLauncher::OnLauncherStopped() { |
| 387 DCHECK(main_message_loop_->BelongsToCurrentThread()); | 386 DCHECK(main_message_loop_->BelongsToCurrentThread()); |
| 388 | 387 |
| 389 DWORD exit_code = CONTROL_C_EXIT; | 388 DWORD exit_code = CONTROL_C_EXIT; |
| 390 if (worker_process_.IsValid()) { | 389 if (worker_process_.IsValid()) { |
| 391 if (!::GetExitCodeProcess(worker_process_, &exit_code)) { | 390 if (!::GetExitCodeProcess(worker_process_, &exit_code)) { |
| 392 LOG_GETLASTERROR(INFO) | 391 LOG_GETLASTERROR(INFO) |
| 393 << "Failed to query the exit code of the worker process"; | 392 << "Failed to query the exit code of the worker process"; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 428 launch_backoff_, TimeDelta::FromSeconds(kMaxLaunchDelaySeconds)); | 427 launch_backoff_, TimeDelta::FromSeconds(kMaxLaunchDelaySeconds)); |
| 429 } | 428 } |
| 430 | 429 |
| 431 // Try to launch the worker process. | 430 // Try to launch the worker process. |
| 432 timer_.Start(FROM_HERE, launch_backoff_, | 431 timer_.Start(FROM_HERE, launch_backoff_, |
| 433 this, &WtsSessionProcessLauncher::LaunchProcess); | 432 this, &WtsSessionProcessLauncher::LaunchProcess); |
| 434 } | 433 } |
| 435 } | 434 } |
| 436 | 435 |
| 437 } // namespace remoting | 436 } // namespace remoting |
| OLD | NEW |