Chromium Code Reviews| 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/host_service.h" | 8 #include "remoting/host/win/host_service.h" |
| 9 | 9 |
| 10 #include <windows.h> | 10 #include <windows.h> |
| 11 #include <shellapi.h> | 11 #include <shellapi.h> |
| 12 #include <wtsapi32.h> | 12 #include <wtsapi32.h> |
| 13 | 13 |
| 14 #include "base/at_exit.h" | 14 #include "base/at_exit.h" |
| 15 #include "base/base_paths.h" | 15 #include "base/base_paths.h" |
| 16 #include "base/base_switches.h" | 16 #include "base/base_switches.h" |
| 17 #include "base/bind.h" | 17 #include "base/bind.h" |
| 18 #include "base/command_line.h" | 18 #include "base/command_line.h" |
| 19 #include "base/file_path.h" | 19 #include "base/file_path.h" |
| 20 #include "base/logging.h" | 20 #include "base/logging.h" |
| 21 #include "base/message_loop.h" | 21 #include "base/message_loop.h" |
| 22 #include "base/single_thread_task_runner.h" | 22 #include "base/single_thread_task_runner.h" |
| 23 #include "base/stringprintf.h" | 23 #include "base/stringprintf.h" |
| 24 #include "base/threading/thread.h" | 24 #include "base/threading/thread.h" |
| 25 #include "base/utf_string_conversions.h" | 25 #include "base/utf_string_conversions.h" |
| 26 #include "base/win/wrapped_window_proc.h" | 26 #include "base/win/wrapped_window_proc.h" |
| 27 #include "remoting/base/auto_message_loop.h" | |
| 28 #include "remoting/base/auto_thread.h" | |
| 27 #include "remoting/base/breakpad.h" | 29 #include "remoting/base/breakpad.h" |
| 28 #include "remoting/base/scoped_sc_handle_win.h" | 30 #include "remoting/base/scoped_sc_handle_win.h" |
| 29 #include "remoting/base/stoppable.h" | 31 #include "remoting/base/stoppable.h" |
| 30 #include "remoting/host/branding.h" | 32 #include "remoting/host/branding.h" |
| 31 | 33 |
| 32 #if defined(REMOTING_MULTI_PROCESS) | 34 #if defined(REMOTING_MULTI_PROCESS) |
| 33 #include "remoting/host/daemon_process.h" | 35 #include "remoting/host/daemon_process.h" |
| 34 #endif // defined(REMOTING_MULTI_PROCESS) | 36 #endif // defined(REMOTING_MULTI_PROCESS) |
| 35 | 37 |
| 36 #include "remoting/host/usage_stats_consent.h" | 38 #include "remoting/host/usage_stats_consent.h" |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 113 } | 115 } |
| 114 | 116 |
| 115 void HostService::RemoveWtsConsoleObserver(WtsConsoleObserver* observer) { | 117 void HostService::RemoveWtsConsoleObserver(WtsConsoleObserver* observer) { |
| 116 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 118 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 117 | 119 |
| 118 console_observers_.RemoveObserver(observer); | 120 console_observers_.RemoveObserver(observer); |
| 119 } | 121 } |
| 120 | 122 |
| 121 void HostService::OnChildStopped() { | 123 void HostService::OnChildStopped() { |
| 122 child_.reset(NULL); | 124 child_.reset(NULL); |
| 123 main_task_runner_->PostTask(FROM_HERE, MessageLoop::QuitClosure()); | 125 main_task_runner_ = NULL; |
| 124 } | 126 } |
| 125 | 127 |
| 126 void HostService::OnSessionChange() { | 128 void HostService::OnSessionChange() { |
| 127 // WTSGetActiveConsoleSessionId is a very cheap API. It basically reads | 129 // WTSGetActiveConsoleSessionId is a very cheap API. It basically reads |
| 128 // a single value from shared memory. Therefore it is better to check if | 130 // a single value from shared memory. Therefore it is better to check if |
| 129 // the console session is still the same every time a session change | 131 // the console session is still the same every time a session change |
| 130 // notification event is posted. This also takes care of coalescing multiple | 132 // notification event is posted. This also takes care of coalescing multiple |
| 131 // events into one since we look at the latest state. | 133 // events into one since we look at the latest state. |
| 132 uint32 console_session_id = WTSGetActiveConsoleSessionId(); | 134 uint32 console_session_id = WTSGetActiveConsoleSessionId(); |
| 133 if (console_session_id_ != console_session_id) { | 135 if (console_session_id_ != console_session_id) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 189 run_routine_ = &HostService::RunInConsole; | 191 run_routine_ = &HostService::RunInConsole; |
| 190 } | 192 } |
| 191 | 193 |
| 192 return true; | 194 return true; |
| 193 } | 195 } |
| 194 | 196 |
| 195 int HostService::Run() { | 197 int HostService::Run() { |
| 196 return (this->*run_routine_)(); | 198 return (this->*run_routine_)(); |
| 197 } | 199 } |
| 198 | 200 |
| 199 void HostService::RunMessageLoop(MessageLoop* message_loop) { | 201 bool HostService::BeforeMessageLoop() { |
| 200 // Launch the I/O thread. | 202 // Launch the I/O thread. |
| 201 base::Thread io_thread(kIoThreadName); | 203 scoped_refptr<AutoThread> io_thread( |
| 204 new AutoThread(kIoThreadName, main_task_runner_)); | |
|
Wez
2012/08/24 21:30:49
Can you instead create a normal Thread in RunMessa
alexeypa (please no reviews)
2012/08/27 21:19:40
Done.
| |
| 202 base::Thread::Options io_thread_options(MessageLoop::TYPE_IO, 0); | 205 base::Thread::Options io_thread_options(MessageLoop::TYPE_IO, 0); |
| 203 if (!io_thread.StartWithOptions(io_thread_options)) { | 206 if (!io_thread->StartWithOptions(io_thread_options)) { |
| 204 LOG(ERROR) << "Failed to start the I/O thread"; | 207 LOG(FATAL) << "Failed to start the I/O thread"; |
| 205 stopped_event_.Signal(); | 208 return false; |
| 206 return; | |
| 207 } | 209 } |
| 208 | 210 |
| 209 #if defined(REMOTING_MULTI_PROCESS) | 211 #if defined(REMOTING_MULTI_PROCESS) |
| 210 | 212 |
| 211 child_ = DaemonProcess::Create( | 213 child_ = DaemonProcess::Create( |
| 212 main_task_runner_, | 214 main_task_runner_, |
| 213 io_thread.message_loop_proxy(), | 215 io_thread, |
| 214 base::Bind(&HostService::OnChildStopped, | 216 base::Bind(&HostService::OnChildStopped, |
| 215 base::Unretained(this))).PassAs<Stoppable>(); | 217 base::Unretained(this))).PassAs<Stoppable>(); |
| 216 | 218 |
| 217 #else // !defined(REMOTING_MULTI_PROCESS) | 219 #else // !defined(REMOTING_MULTI_PROCESS) |
| 218 | 220 |
| 219 // Create the session process launcher. | 221 // Create the session process launcher. |
| 220 child_.reset(new WtsSessionProcessLauncher( | 222 child_.reset(new WtsSessionProcessLauncher( |
| 221 base::Bind(&HostService::OnChildStopped, base::Unretained(this)), | 223 base::Bind(&HostService::OnChildStopped, base::Unretained(this)), |
| 222 this, | 224 this, |
| 223 main_task_runner_, | 225 main_task_runner_, |
| 224 io_thread.message_loop_proxy())); | 226 io_thread)); |
| 225 | 227 |
| 226 #endif // !defined(REMOTING_MULTI_PROCESS) | 228 #endif // !defined(REMOTING_MULTI_PROCESS) |
| 227 | 229 |
| 230 return true; | |
| 231 } | |
| 232 | |
| 233 void HostService::RunMessageLoop(MessageLoop* message_loop) { | |
| 228 // Run the service. | 234 // Run the service. |
| 229 message_loop->Run(); | 235 if (BeforeMessageLoop()) { |
| 236 message_loop->Run(); | |
| 237 } | |
| 230 | 238 |
| 231 // Release the control handler. | 239 // Release the control handler. |
| 232 stopped_event_.Signal(); | 240 stopped_event_.Signal(); |
| 233 } | 241 } |
| 234 | 242 |
| 235 int HostService::Elevate() { | 243 int HostService::Elevate() { |
| 236 // Get the name of the binary to launch. | 244 // Get the name of the binary to launch. |
| 237 FilePath binary = | 245 FilePath binary = |
| 238 CommandLine::ForCurrentProcess()->GetSwitchValuePath(kElevateSwitchName); | 246 CommandLine::ForCurrentProcess()->GetSwitchValuePath(kElevateSwitchName); |
| 239 | 247 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 272 << "Failed to connect to the service control manager"; | 280 << "Failed to connect to the service control manager"; |
| 273 return kErrorExitCode; | 281 return kErrorExitCode; |
| 274 } | 282 } |
| 275 | 283 |
| 276 return kSuccessExitCode; | 284 return kSuccessExitCode; |
| 277 } | 285 } |
| 278 | 286 |
| 279 int HostService::RunInConsole() { | 287 int HostService::RunInConsole() { |
| 280 MessageLoop message_loop(MessageLoop::TYPE_UI); | 288 MessageLoop message_loop(MessageLoop::TYPE_UI); |
| 281 | 289 |
| 282 // Allow other threads to post to our message loop. | 290 // Keep a reference to the main message loop while it is used. Once the last |
| 283 main_task_runner_ = message_loop.message_loop_proxy(); | 291 // reference is dropped QuitClosure() will be posted to the loop. |
| 292 main_task_runner_ = new AutoMessageLoop(&message_loop); | |
| 284 | 293 |
| 285 int result = kErrorExitCode; | 294 int result = kErrorExitCode; |
| 286 | 295 |
| 287 // Subscribe to Ctrl-C and other console events. | 296 // Subscribe to Ctrl-C and other console events. |
| 288 if (!SetConsoleCtrlHandler(&HostService::ConsoleControlHandler, TRUE)) { | 297 if (!SetConsoleCtrlHandler(&HostService::ConsoleControlHandler, TRUE)) { |
| 289 LOG_GETLASTERROR(ERROR) | 298 LOG_GETLASTERROR(ERROR) |
| 290 << "Failed to set console control handler"; | 299 << "Failed to set console control handler"; |
| 291 return result; | 300 return result; |
| 292 } | 301 } |
| 293 | 302 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 368 self->main_task_runner_->PostTask(FROM_HERE, base::Bind( | 377 self->main_task_runner_->PostTask(FROM_HERE, base::Bind( |
| 369 &HostService::OnSessionChange, base::Unretained(self))); | 378 &HostService::OnSessionChange, base::Unretained(self))); |
| 370 return NO_ERROR; | 379 return NO_ERROR; |
| 371 | 380 |
| 372 default: | 381 default: |
| 373 return ERROR_CALL_NOT_IMPLEMENTED; | 382 return ERROR_CALL_NOT_IMPLEMENTED; |
| 374 } | 383 } |
| 375 } | 384 } |
| 376 | 385 |
| 377 VOID WINAPI HostService::ServiceMain(DWORD argc, WCHAR* argv[]) { | 386 VOID WINAPI HostService::ServiceMain(DWORD argc, WCHAR* argv[]) { |
| 378 MessageLoop message_loop; | 387 MessageLoop message_loop(MessageLoop::TYPE_DEFAULT); |
| 379 | 388 |
| 380 // Allow other threads to post to our message loop. | 389 // Keep a reference to the main message loop while it is used. Once the last |
| 390 // reference is dropped QuitClosure() will be posted to the loop. | |
| 381 HostService* self = HostService::GetInstance(); | 391 HostService* self = HostService::GetInstance(); |
| 382 self->main_task_runner_ = message_loop.message_loop_proxy(); | 392 self->main_task_runner_ = new AutoMessageLoop(&message_loop); |
| 383 | 393 |
| 384 // Register the service control handler. | 394 // Register the service control handler. |
| 385 self->service_status_handle_ = | 395 self->service_status_handle_ = |
| 386 RegisterServiceCtrlHandlerExW(kWindowsServiceName, | 396 RegisterServiceCtrlHandlerExW(kWindowsServiceName, |
| 387 &HostService::ServiceControlHandler, | 397 &HostService::ServiceControlHandler, |
| 388 self); | 398 self); |
| 389 if (self->service_status_handle_ == 0) { | 399 if (self->service_status_handle_ == 0) { |
| 390 LOG_GETLASTERROR(ERROR) | 400 LOG_GETLASTERROR(ERROR) |
| 391 << "Failed to register the service control handler"; | 401 << "Failed to register the service control handler"; |
| 392 return; | 402 return; |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 480 } | 490 } |
| 481 | 491 |
| 482 remoting::HostService* service = remoting::HostService::GetInstance(); | 492 remoting::HostService* service = remoting::HostService::GetInstance(); |
| 483 if (!service->InitWithCommandLine(command_line)) { | 493 if (!service->InitWithCommandLine(command_line)) { |
| 484 usage(command_line->GetProgram()); | 494 usage(command_line->GetProgram()); |
| 485 return kUsageExitCode; | 495 return kUsageExitCode; |
| 486 } | 496 } |
| 487 | 497 |
| 488 return service->Run(); | 498 return service->Run(); |
| 489 } | 499 } |
| OLD | NEW |