15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file implements the Windows service controlling Me2Me host processes 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// running within user sessions. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/win/host_service.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sddl.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <wtsapi32.h> 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_paths.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_switches.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 199ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/run_loop.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/single_thread_task_runner.h" 22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h" 24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/win/message_window.h" 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/win/scoped_com_initializer.h" 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/base/auto_thread.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/base/scoped_sc_handle_win.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/branding.h" 2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "remoting/host/daemon_process.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/host_exit_codes.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/logging.h" 327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "remoting/host/win/com_security.h" 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/host/win/core_resource.h" 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/host/win/wts_terminal_observer.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace remoting { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kIoThreadName[] = "I/O thread"; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Command line switches: 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "--console" runs the service interactively for debugging purposes. 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kConsoleSwitchName[] = "console"; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Security descriptor allowing local processes running under SYSTEM or 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// LocalService accounts to call COM methods exposed by the daemon. 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const wchar_t kComProcessSd[] = 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SDDL_OWNER L":" SDDL_LOCAL_SYSTEM 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SDDL_GROUP L":" SDDL_LOCAL_SYSTEM 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SDDL_DACL L":" 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SDDL_ACE(SDDL_ACCESS_ALLOWED, SDDL_COM_EXECUTE_LOCAL, SDDL_LOCAL_SYSTEM) 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SDDL_ACE(SDDL_ACCESS_ALLOWED, SDDL_COM_EXECUTE_LOCAL, SDDL_LOCAL_SERVICE); 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Appended to |kComProcessSd| to specify that only callers running at medium or 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// higher integrity level are allowed to call COM methods exposed by the daemon. 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const wchar_t kComProcessMandatoryLabel[] = 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SDDL_SACL L":" 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SDDL_ACE(SDDL_MANDATORY_LABEL, SDDL_NO_EXECUTE_UP, SDDL_ML_MEDIUM); 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HostService* HostService::GetInstance() { 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return Singleton<HostService>::get(); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool HostService::InitWithCommandLine(const base::CommandLine* command_line) { 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::CommandLine::StringVector args = command_line->GetArgs(); 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!args.empty()) { 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "No positional parameters expected."; 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Run interactively if needed. 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (run_routine_ == &HostService::RunAsService && 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) command_line->HasSwitch(kConsoleSwitchName)) { 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) run_routine_ = &HostService::RunInConsole; 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int HostService::Run() { 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return (this->*run_routine_)(); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool HostService::AddWtsTerminalObserver(const std::string& terminal_id, 89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch WtsTerminalObserver* observer) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(main_task_runner_->BelongsToCurrentThread()); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RegisteredObserver registered_observer; 93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch registered_observer.terminal_id = terminal_id; 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) registered_observer.session_id = kInvalidSessionId; 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) registered_observer.observer = observer; 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool session_id_found = false; 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::list<RegisteredObserver>::const_iterator i; 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (i = observers_.begin(); i != observers_.end(); ++i) { 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Get the attached session ID from another observer watching the same WTS 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // console if any. 102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (i->terminal_id == terminal_id) { 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) registered_observer.session_id = i->session_id; 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_id_found = true; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Check that |observer| hasn't been registered already. 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (i->observer == observer) 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // If |terminal_id| is new, enumerate all sessions to see if there is one 113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // attached to |terminal_id|. 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!session_id_found) 115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch registered_observer.session_id = LookupSessionId(terminal_id); 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) observers_.push_back(registered_observer); 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (registered_observer.session_id != kInvalidSessionId) { 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) observer->OnSessionAttached(registered_observer.session_id); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HostService::RemoveWtsTerminalObserver(WtsTerminalObserver* observer) { 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(main_task_runner_->BelongsToCurrentThread()); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::list<RegisteredObserver>::const_iterator i; 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (i = observers_.begin(); i != observers_.end(); ++i) { 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (i->observer == observer) { 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) observers_.erase(i); 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HostService::HostService() : 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) run_routine_(&HostService::RunAsService), 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) service_status_handle_(0), 141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) stopped_event_(true, false), 142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) weak_factory_(this) { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HostService::~HostService() { 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HostService::OnSessionChange(uint32 event, uint32 session_id) { 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(main_task_runner_->BelongsToCurrentThread()); 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_NE(session_id, kInvalidSessionId); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Process only attach/detach notifications. 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (event != WTS_CONSOLE_CONNECT && event != WTS_CONSOLE_DISCONNECT && 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event != WTS_REMOTE_CONNECT && event != WTS_REMOTE_DISCONNECT) { 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Assuming that notification can arrive later query the current state of 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |session_id|. 160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string terminal_id; 161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool attached = LookupTerminalId(session_id, &terminal_id); 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::list<RegisteredObserver>::iterator i = observers_.begin(); 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (i != observers_.end()) { 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::list<RegisteredObserver>::iterator next = i; 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++next; 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Issue a detach notification if the session was detached from a client or 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // if it is now attached to a different client. 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (i->session_id == session_id && 171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (!attached || !(i->terminal_id == terminal_id))) { 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) i->session_id = kInvalidSessionId; 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) i->observer->OnSessionDetached(); 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) i = next; 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The client currently attached to |session_id| was attached to a different 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // session before. Reconnect it to |session_id|. 180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (attached && i->terminal_id == terminal_id && 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) i->session_id != session_id) { 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WtsTerminalObserver* observer = i->observer; 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (i->session_id != kInvalidSessionId) { 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) i->session_id = kInvalidSessionId; 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) i->observer->OnSessionDetached(); 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Verify that OnSessionDetached() above didn't remove |observer| 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // from the list. 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::list<RegisteredObserver>::iterator j = next; 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) --j; 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (j->observer == observer) { 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) j->session_id = session_id; 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) observer->OnSessionAttached(session_id); 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) i = next; 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HostService::CreateLauncher( 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<AutoThreadTaskRunner> task_runner) { 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Launch the I/O thread. 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<AutoThreadTaskRunner> io_task_runner = 207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) AutoThread::CreateWithType( 208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kIoThreadName, task_runner, base::MessageLoop::TYPE_IO); 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!io_task_runner) { 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(FATAL) << "Failed to start the I/O thread"; 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) daemon_process_ = DaemonProcess::Create( 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) task_runner, 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_task_runner, 217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::Bind(&HostService::StopDaemonProcess, weak_ptr_)); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HostService::RunAsService() { 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SERVICE_TABLE_ENTRYW dispatch_table[] = { 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { const_cast<LPWSTR>(kWindowsServiceName), &HostService::ServiceMain }, 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { NULL, NULL } 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!StartServiceCtrlDispatcherW(dispatch_table)) { 227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PLOG(ERROR) << "Failed to connect to the service control manager"; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kInitializationFailed; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Wait until the service thread completely exited to avoid concurrent 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // teardown of objects registered with base::AtExitManager and object 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // destoyed by the service thread. 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stopped_event_.Wait(); 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kSuccessExitCode; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HostService::RunAsServiceImpl() { 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::MessageLoopForUI message_loop; 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::RunLoop run_loop; 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) main_task_runner_ = message_loop.message_loop_proxy(); 243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) weak_ptr_ = weak_factory_.GetWeakPtr(); 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Register the service control handler. 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) service_status_handle_ = RegisterServiceCtrlHandlerExW( 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kWindowsServiceName, &HostService::ServiceControlHandler, this); 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (service_status_handle_ == 0) { 249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PLOG(ERROR) << "Failed to register the service control handler"; 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Report running status of the service. 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SERVICE_STATUS service_status; 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ZeroMemory(&service_status, sizeof(service_status)); 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) service_status.dwCurrentState = SERVICE_RUNNING; 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) service_status.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN | 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SERVICE_ACCEPT_STOP | 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SERVICE_ACCEPT_SESSIONCHANGE; 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) service_status.dwWin32ExitCode = kSuccessExitCode; 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!SetServiceStatus(service_status_handle_, &service_status)) { 263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PLOG(ERROR) 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "Failed to report service status to the service control manager"; 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Initialize COM. 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::win::ScopedCOMInitializer com_initializer; 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!com_initializer.succeeded()) 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!InitializeComSecurity(base::WideToUTF8(kComProcessSd), 2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::WideToUTF8(kComProcessMandatoryLabel), 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) false)) { 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 2777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateLauncher(scoped_refptr<AutoThreadTaskRunner>( 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new AutoThreadTaskRunner(main_task_runner_, 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) run_loop.QuitClosure()))); 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Run the service. 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) run_loop.Run(); 285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) weak_factory_.InvalidateWeakPtrs(); 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Tell SCM that the service is stopped. 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) service_status.dwCurrentState = SERVICE_STOPPED; 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) service_status.dwControlsAccepted = 0; 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!SetServiceStatus(service_status_handle_, &service_status)) { 291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PLOG(ERROR) 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "Failed to report service status to the service control manager"; 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int HostService::RunInConsole() { 2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::MessageLoopForUI message_loop; 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::RunLoop run_loop; 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) main_task_runner_ = message_loop.message_loop_proxy(); 301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) weak_ptr_ = weak_factory_.GetWeakPtr(); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = kInitializationFailed; 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Initialize COM. 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::win::ScopedCOMInitializer com_initializer; 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!com_initializer.succeeded()) 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return result; 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!InitializeComSecurity(base::WideToUTF8(kComProcessSd), 3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::WideToUTF8(kComProcessMandatoryLabel), 3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) false)) { 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return result; 3147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Subscribe to Ctrl-C and other console events. 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SetConsoleCtrlHandler(&HostService::ConsoleControlHandler, TRUE)) { 318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PLOG(ERROR) << "Failed to set console control handler"; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a window for receiving session change notifications. 323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::win::MessageWindow window; 324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!window.Create(base::Bind(&HostService::HandleMessage, 325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Unretained(this)))) { 326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PLOG(ERROR) << "Failed to create the session notification window"; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto cleanup; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Subscribe to session change notifications. 331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (WTSRegisterSessionNotification(window.hwnd(), 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTIFY_FOR_ALL_SESSIONS) != FALSE) { 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateLauncher(scoped_refptr<AutoThreadTaskRunner>( 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new AutoThreadTaskRunner(main_task_runner_, 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) run_loop.QuitClosure()))); 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Run the service. 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) run_loop.Run(); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Release the control handler. 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stopped_event_.Signal(); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) WTSUnRegisterSessionNotification(window.hwnd()); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = kSuccessExitCode; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)cleanup: 348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) weak_factory_.InvalidateWeakPtrs(); 349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unsubscribe from console events. Ignore the exit code. There is nothing 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we can do about it now and the program is about to exit anyway. Even if 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it crashes nothing is going to be broken because of it. 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetConsoleCtrlHandler(&HostService::ConsoleControlHandler, FALSE); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void HostService::StopDaemonProcess() { 359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(main_task_runner_->BelongsToCurrentThread()); 360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) daemon_process_.reset(); 362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool HostService::HandleMessage( 365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch UINT message, WPARAM wparam, LPARAM lparam, LRESULT* result) { 366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (message == WM_WTSSESSION_CHANGE) { 367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) OnSessionChange(wparam, lparam); 368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *result = 0; 369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)BOOL WINAPI HostService::ConsoleControlHandler(DWORD event) { 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HostService* self = HostService::GetInstance(); 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (event) { 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case CTRL_C_EVENT: 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case CTRL_BREAK_EVENT: 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case CTRL_CLOSE_EVENT: 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case CTRL_LOGOFF_EVENT: 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case CTRL_SHUTDOWN_EVENT: 384868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) self->main_task_runner_->PostTask( 385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FROM_HERE, base::Bind(&HostService::StopDaemonProcess, 386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) self->weak_ptr_)); 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return TRUE; 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default: 3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return FALSE; 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DWORD WINAPI HostService::ServiceControlHandler(DWORD control, 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD event_type, 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LPVOID event_data, 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LPVOID context) { 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HostService* self = reinterpret_cast<HostService*>(context); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (control) { 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SERVICE_CONTROL_INTERROGATE: 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NO_ERROR; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SERVICE_CONTROL_SHUTDOWN: 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SERVICE_CONTROL_STOP: 406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) self->main_task_runner_->PostTask( 407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FROM_HERE, base::Bind(&HostService::StopDaemonProcess, 408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) self->weak_ptr_)); 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NO_ERROR; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SERVICE_CONTROL_SESSIONCHANGE: 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self->main_task_runner_->PostTask(FROM_HERE, base::Bind( 413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) &HostService::OnSessionChange, self->weak_ptr_, event_type, 4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reinterpret_cast<WTSSESSION_NOTIFICATION*>(event_data)->dwSessionId)); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NO_ERROR; 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERROR_CALL_NOT_IMPLEMENTED; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VOID WINAPI HostService::ServiceMain(DWORD argc, WCHAR* argv[]) { 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HostService* self = HostService::GetInstance(); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Run the service. 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self->RunAsServiceImpl(); 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Release the control handler and notify the main thread that it can exit 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // now. 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self->stopped_event_.Signal(); 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int DaemonProcessMain() { 4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HostService* service = HostService::GetInstance(); 436cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!service->InitWithCommandLine(base::CommandLine::ForCurrentProcess())) { 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return kUsageExitCode; 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return service->Run(); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 443cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} // namespace remoting 444