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

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

Issue 16143004: Use a weak pointer to post service control events and session change notifications. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 6 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
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/host_service.h" 8 #include "remoting/host/win/host_service.h"
9 9
10 #include <sddl.h> 10 #include <sddl.h>
11 #include <windows.h> 11 #include <windows.h>
12 #include <wtsapi32.h> 12 #include <wtsapi32.h>
13 13
14 #include "base/base_paths.h" 14 #include "base/base_paths.h"
15 #include "base/base_switches.h" 15 #include "base/base_switches.h"
16 #include "base/bind.h" 16 #include "base/bind.h"
17 #include "base/command_line.h" 17 #include "base/command_line.h"
18 #include "base/files/file_path.h" 18 #include "base/files/file_path.h"
19 #include "base/message_loop.h" 19 #include "base/message_loop.h"
20 #include "base/run_loop.h" 20 #include "base/run_loop.h"
21 #include "base/single_thread_task_runner.h" 21 #include "base/single_thread_task_runner.h"
22 #include "base/threading/thread.h" 22 #include "base/threading/thread.h"
23 #include "base/utf_string_conversions.h" 23 #include "base/utf_string_conversions.h"
24 #include "base/win/scoped_com_initializer.h" 24 #include "base/win/scoped_com_initializer.h"
25 #include "base/win/windows_version.h" 25 #include "base/win/windows_version.h"
26 #include "remoting/base/auto_thread.h" 26 #include "remoting/base/auto_thread.h"
27 #include "remoting/base/scoped_sc_handle_win.h" 27 #include "remoting/base/scoped_sc_handle_win.h"
28 #include "remoting/base/stoppable.h"
29 #include "remoting/host/branding.h" 28 #include "remoting/host/branding.h"
30 #include "remoting/host/daemon_process.h" 29 #include "remoting/host/daemon_process.h"
31 #include "remoting/host/host_exit_codes.h" 30 #include "remoting/host/host_exit_codes.h"
32 #include "remoting/host/logging.h" 31 #include "remoting/host/logging.h"
33 #include "remoting/host/win/core_resource.h" 32 #include "remoting/host/win/core_resource.h"
34 #include "remoting/host/win/security_descriptor.h" 33 #include "remoting/host/win/security_descriptor.h"
35 #include "remoting/host/win/wts_terminal_observer.h" 34 #include "remoting/host/win/wts_terminal_observer.h"
36 35
37 namespace remoting { 36 namespace remoting {
38 37
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 if (i->observer == observer) { 195 if (i->observer == observer) {
197 observers_.erase(i); 196 observers_.erase(i);
198 return; 197 return;
199 } 198 }
200 } 199 }
201 } 200 }
202 201
203 HostService::HostService() : 202 HostService::HostService() :
204 run_routine_(&HostService::RunAsService), 203 run_routine_(&HostService::RunAsService),
205 service_status_handle_(0), 204 service_status_handle_(0),
206 stopped_event_(true, false) { 205 stopped_event_(true, false),
206 weak_factory_(this) {
207 } 207 }
208 208
209 HostService::~HostService() { 209 HostService::~HostService() {
210 } 210 }
211 211
212 void HostService::OnSessionChange(uint32 event, uint32 session_id) { 212 void HostService::OnSessionChange(uint32 event, uint32 session_id) {
213 DCHECK(main_task_runner_->BelongsToCurrentThread()); 213 DCHECK(main_task_runner_->BelongsToCurrentThread());
214 DCHECK_NE(session_id, kInvalidSessionId); 214 DCHECK_NE(session_id, kInvalidSessionId);
215 215
216 // Process only attach/detach notifications. 216 // Process only attach/detach notifications.
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 scoped_refptr<AutoThreadTaskRunner> task_runner) { 268 scoped_refptr<AutoThreadTaskRunner> task_runner) {
269 // Launch the I/O thread. 269 // Launch the I/O thread.
270 scoped_refptr<AutoThreadTaskRunner> io_task_runner = 270 scoped_refptr<AutoThreadTaskRunner> io_task_runner =
271 AutoThread::CreateWithType( 271 AutoThread::CreateWithType(
272 kIoThreadName, task_runner, base::MessageLoop::TYPE_IO); 272 kIoThreadName, task_runner, base::MessageLoop::TYPE_IO);
273 if (!io_task_runner) { 273 if (!io_task_runner) {
274 LOG(FATAL) << "Failed to start the I/O thread"; 274 LOG(FATAL) << "Failed to start the I/O thread";
275 return; 275 return;
276 } 276 }
277 277
278 child_ = DaemonProcess::Create( 278 daemon_process_ = DaemonProcess::Create(
279 task_runner, 279 task_runner,
280 io_task_runner, 280 io_task_runner,
281 base::Bind(&HostService::OnChildStopped, 281 base::Bind(&HostService::StopDaemonProcess, weak_self_));
282 base::Unretained(this))).PassAs<Stoppable>();
283 }
284
285 void HostService::OnChildStopped() {
286 DCHECK(main_task_runner_->BelongsToCurrentThread());
287
288 child_.reset(NULL);
289 } 282 }
290 283
291 int HostService::RunAsService() { 284 int HostService::RunAsService() {
292 SERVICE_TABLE_ENTRYW dispatch_table[] = { 285 SERVICE_TABLE_ENTRYW dispatch_table[] = {
293 { const_cast<LPWSTR>(kWindowsServiceName), &HostService::ServiceMain }, 286 { const_cast<LPWSTR>(kWindowsServiceName), &HostService::ServiceMain },
294 { NULL, NULL } 287 { NULL, NULL }
295 }; 288 };
296 289
297 if (!StartServiceCtrlDispatcherW(dispatch_table)) { 290 if (!StartServiceCtrlDispatcherW(dispatch_table)) {
298 LOG_GETLASTERROR(ERROR) 291 LOG_GETLASTERROR(ERROR)
299 << "Failed to connect to the service control manager"; 292 << "Failed to connect to the service control manager";
300 return kInitializationFailed; 293 return kInitializationFailed;
301 } 294 }
302 295
303 // Wait until the service thread completely exited to avoid concurrent 296 // Wait until the service thread completely exited to avoid concurrent
304 // teardown of objects registered with base::AtExitManager and object 297 // teardown of objects registered with base::AtExitManager and object
305 // destoyed by the service thread. 298 // destoyed by the service thread.
306 stopped_event_.Wait(); 299 stopped_event_.Wait();
307 300
308 return kSuccessExitCode; 301 return kSuccessExitCode;
309 } 302 }
310 303
311 void HostService::RunAsServiceImpl() { 304 void HostService::RunAsServiceImpl() {
312 base::MessageLoop message_loop(base::MessageLoop::TYPE_UI); 305 base::MessageLoop message_loop(base::MessageLoop::TYPE_UI);
313 base::RunLoop run_loop; 306 base::RunLoop run_loop;
314 main_task_runner_ = message_loop.message_loop_proxy(); 307 main_task_runner_ = message_loop.message_loop_proxy();
308 weak_self_ = weak_factory_.GetWeakPtr();
315 309
316 // Register the service control handler. 310 // Register the service control handler.
317 service_status_handle_ = RegisterServiceCtrlHandlerExW( 311 service_status_handle_ = RegisterServiceCtrlHandlerExW(
318 kWindowsServiceName, &HostService::ServiceControlHandler, this); 312 kWindowsServiceName, &HostService::ServiceControlHandler, this);
319 if (service_status_handle_ == 0) { 313 if (service_status_handle_ == 0) {
320 LOG_GETLASTERROR(ERROR) 314 LOG_GETLASTERROR(ERROR)
321 << "Failed to register the service control handler"; 315 << "Failed to register the service control handler";
322 return; 316 return;
323 } 317 }
324 318
(...skipping 19 matching lines...) Expand all
344 338
345 if (!InitializeComSecurity()) 339 if (!InitializeComSecurity())
346 return; 340 return;
347 341
348 CreateLauncher(scoped_refptr<AutoThreadTaskRunner>( 342 CreateLauncher(scoped_refptr<AutoThreadTaskRunner>(
349 new AutoThreadTaskRunner(main_task_runner_, 343 new AutoThreadTaskRunner(main_task_runner_,
350 run_loop.QuitClosure()))); 344 run_loop.QuitClosure())));
351 345
352 // Run the service. 346 // Run the service.
353 run_loop.Run(); 347 run_loop.Run();
348 weak_factory_.InvalidateWeakPtrs();
354 349
355 // Tell SCM that the service is stopped. 350 // Tell SCM that the service is stopped.
356 service_status.dwCurrentState = SERVICE_STOPPED; 351 service_status.dwCurrentState = SERVICE_STOPPED;
357 service_status.dwControlsAccepted = 0; 352 service_status.dwControlsAccepted = 0;
358 if (!SetServiceStatus(service_status_handle_, &service_status)) { 353 if (!SetServiceStatus(service_status_handle_, &service_status)) {
359 LOG_GETLASTERROR(ERROR) 354 LOG_GETLASTERROR(ERROR)
360 << "Failed to report service status to the service control manager"; 355 << "Failed to report service status to the service control manager";
361 return; 356 return;
362 } 357 }
363 } 358 }
364 359
365 int HostService::RunInConsole() { 360 int HostService::RunInConsole() {
366 base::MessageLoop message_loop(base::MessageLoop::TYPE_UI); 361 base::MessageLoop message_loop(base::MessageLoop::TYPE_UI);
367 base::RunLoop run_loop; 362 base::RunLoop run_loop;
368 main_task_runner_ = message_loop.message_loop_proxy(); 363 main_task_runner_ = message_loop.message_loop_proxy();
364 weak_self_ = weak_factory_.GetWeakPtr();
369 365
370 int result = kInitializationFailed; 366 int result = kInitializationFailed;
371 367
372 // Initialize COM. 368 // Initialize COM.
373 base::win::ScopedCOMInitializer com_initializer; 369 base::win::ScopedCOMInitializer com_initializer;
374 if (!com_initializer.succeeded()) 370 if (!com_initializer.succeeded())
375 return result; 371 return result;
376 372
377 if (!InitializeComSecurity()) 373 if (!InitializeComSecurity())
378 return result; 374 return result;
(...skipping 24 matching lines...) Expand all
403 run_loop.Run(); 399 run_loop.Run();
404 400
405 // Release the control handler. 401 // Release the control handler.
406 stopped_event_.Signal(); 402 stopped_event_.Signal();
407 403
408 WTSUnRegisterSessionNotification(window.hwnd()); 404 WTSUnRegisterSessionNotification(window.hwnd());
409 result = kSuccessExitCode; 405 result = kSuccessExitCode;
410 } 406 }
411 407
412 cleanup: 408 cleanup:
409 weak_factory_.InvalidateWeakPtrs();
410
413 // Unsubscribe from console events. Ignore the exit code. There is nothing 411 // Unsubscribe from console events. Ignore the exit code. There is nothing
414 // we can do about it now and the program is about to exit anyway. Even if 412 // we can do about it now and the program is about to exit anyway. Even if
415 // it crashes nothing is going to be broken because of it. 413 // it crashes nothing is going to be broken because of it.
416 SetConsoleCtrlHandler(&HostService::ConsoleControlHandler, FALSE); 414 SetConsoleCtrlHandler(&HostService::ConsoleControlHandler, FALSE);
417 415
418 return result; 416 return result;
419 } 417 }
420 418
419 void HostService::StopDaemonProcess() {
420 DCHECK(main_task_runner_->BelongsToCurrentThread());
421
422 daemon_process_.reset(NULL);
Wez 2013/06/07 17:48:24 nit: No need for explicit NULL.
alexeypa (please no reviews) 2013/06/07 18:30:23 Done.
423 }
424
421 bool HostService::HandleMessage( 425 bool HostService::HandleMessage(
422 HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam, LRESULT* result) { 426 HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam, LRESULT* result) {
423 if (message == WM_WTSSESSION_CHANGE) { 427 if (message == WM_WTSSESSION_CHANGE) {
424 OnSessionChange(wparam, lparam); 428 OnSessionChange(wparam, lparam);
425 *result = 0; 429 *result = 0;
426 return true; 430 return true;
427 } 431 }
428 432
429 return false; 433 return false;
430 } 434 }
431 435
432 // static 436 // static
433 BOOL WINAPI HostService::ConsoleControlHandler(DWORD event) { 437 BOOL WINAPI HostService::ConsoleControlHandler(DWORD event) {
434 HostService* self = HostService::GetInstance(); 438 HostService* self = HostService::GetInstance();
435 switch (event) { 439 switch (event) {
436 case CTRL_C_EVENT: 440 case CTRL_C_EVENT:
437 case CTRL_BREAK_EVENT: 441 case CTRL_BREAK_EVENT:
438 case CTRL_CLOSE_EVENT: 442 case CTRL_CLOSE_EVENT:
439 case CTRL_LOGOFF_EVENT: 443 case CTRL_LOGOFF_EVENT:
440 case CTRL_SHUTDOWN_EVENT: 444 case CTRL_SHUTDOWN_EVENT:
441 self->main_task_runner_->PostTask(FROM_HERE, base::Bind( 445 self->main_task_runner_->PostTask(
442 &Stoppable::Stop, base::Unretained(self->child_.get()))); 446 FROM_HERE, base::Bind(&HostService::StopDaemonProcess,
443 self->stopped_event_.Wait(); 447 self->weak_self_));
444 return TRUE; 448 return TRUE;
445 449
446 default: 450 default:
447 return FALSE; 451 return FALSE;
448 } 452 }
449 } 453 }
450 454
451 // static 455 // static
452 DWORD WINAPI HostService::ServiceControlHandler(DWORD control, 456 DWORD WINAPI HostService::ServiceControlHandler(DWORD control,
453 DWORD event_type, 457 DWORD event_type,
454 LPVOID event_data, 458 LPVOID event_data,
455 LPVOID context) { 459 LPVOID context) {
456 HostService* self = reinterpret_cast<HostService*>(context); 460 HostService* self = reinterpret_cast<HostService*>(context);
457 switch (control) { 461 switch (control) {
458 case SERVICE_CONTROL_INTERROGATE: 462 case SERVICE_CONTROL_INTERROGATE:
459 return NO_ERROR; 463 return NO_ERROR;
460 464
461 case SERVICE_CONTROL_SHUTDOWN: 465 case SERVICE_CONTROL_SHUTDOWN:
462 case SERVICE_CONTROL_STOP: 466 case SERVICE_CONTROL_STOP:
463 self->main_task_runner_->PostTask(FROM_HERE, base::Bind( 467 self->main_task_runner_->PostTask(
464 &Stoppable::Stop, base::Unretained(self->child_.get()))); 468 FROM_HERE, base::Bind(&HostService::StopDaemonProcess,
465 self->stopped_event_.Wait(); 469 self->weak_self_));
466 return NO_ERROR; 470 return NO_ERROR;
467 471
468 case SERVICE_CONTROL_SESSIONCHANGE: 472 case SERVICE_CONTROL_SESSIONCHANGE:
469 self->main_task_runner_->PostTask(FROM_HERE, base::Bind( 473 self->main_task_runner_->PostTask(FROM_HERE, base::Bind(
470 &HostService::OnSessionChange, base::Unretained(self), event_type, 474 &HostService::OnSessionChange, self->weak_self_, event_type,
471 reinterpret_cast<WTSSESSION_NOTIFICATION*>(event_data)->dwSessionId)); 475 reinterpret_cast<WTSSESSION_NOTIFICATION*>(event_data)->dwSessionId));
472 return NO_ERROR; 476 return NO_ERROR;
473 477
474 default: 478 default:
475 return ERROR_CALL_NOT_IMPLEMENTED; 479 return ERROR_CALL_NOT_IMPLEMENTED;
476 } 480 }
477 } 481 }
478 482
479 // static 483 // static
480 VOID WINAPI HostService::ServiceMain(DWORD argc, WCHAR* argv[]) { 484 VOID WINAPI HostService::ServiceMain(DWORD argc, WCHAR* argv[]) {
(...skipping 10 matching lines...) Expand all
491 int DaemonProcessMain() { 495 int DaemonProcessMain() {
492 HostService* service = HostService::GetInstance(); 496 HostService* service = HostService::GetInstance();
493 if (!service->InitWithCommandLine(CommandLine::ForCurrentProcess())) { 497 if (!service->InitWithCommandLine(CommandLine::ForCurrentProcess())) {
494 return kUsageExitCode; 498 return kUsageExitCode;
495 } 499 }
496 500
497 return service->Run(); 501 return service->Run();
498 } 502 }
499 503
500 } // namespace remoting 504 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698