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

Unified Diff: remoting/host/host_service_win.cc

Issue 10832068: Moving Windows-only files: remoting/host -> remoting/host/win. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 5 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « remoting/host/host_service_win.h ('k') | remoting/host/launch_process_in_session_win.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: remoting/host/host_service_win.cc
===================================================================
--- remoting/host/host_service_win.cc (revision 149037)
+++ remoting/host/host_service_win.cc (working copy)
@@ -1,447 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// This file implements the Windows service controlling Me2Me host processes
-// running within user sessions.
-
-#include "remoting/host/host_service_win.h"
-
-#include <windows.h>
-#include <wtsapi32.h>
-#include <stdio.h>
-
-#include "base/at_exit.h"
-#include "base/base_paths.h"
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/file_util.h"
-#include "base/logging.h"
-#include "base/message_loop.h"
-#include "base/path_service.h"
-#include "base/stringprintf.h"
-#include "base/threading/thread.h"
-#include "base/utf_string_conversions.h"
-#include "base/win/wrapped_window_proc.h"
-#include "remoting/base/breakpad.h"
-#include "remoting/base/scoped_sc_handle_win.h"
-#include "remoting/host/branding.h"
-#include "remoting/host/host_service_resource.h"
-#include "remoting/host/usage_stats_consent.h"
-#include "remoting/host/wts_console_observer_win.h"
-#include "remoting/host/wts_session_process_launcher_win.h"
-
-using base::StringPrintf;
-
-namespace {
-
-const char kIoThreadName[] = "I/O thread";
-
-// A window class for the session change notifications window.
-const wchar_t kSessionNotificationWindowClass[] =
- L"Chromoting_SessionNotificationWindow";
-
-// Command line actions and switches:
-// "run" sumply runs the service as usual.
-const wchar_t kRunActionName[] = L"run";
-
-// "--console" runs the service interactively for debugging purposes.
-const char kConsoleSwitchName[] = "console";
-
-// "--host-binary" specifies the host binary to run in console session.
-const char kHostBinarySwitchName[] = "host-binary";
-
-// "--help" or "--?" prints the usage message.
-const char kHelpSwitchName[] = "help";
-const char kQuestionSwitchName[] = "?";
-
-const char kUsageMessage[] =
- "\n"
- "Usage: %s [action] [options]\n"
- "\n"
- "Actions:\n"
- " run - Run the service (default if no action was specified).\n"
- "\n"
- "Options:\n"
- " --console - Run the service interactively for debugging purposes.\n"
- " --host-binary - Specifies the host binary to run.\n"
- " --help, --? - Print this message.\n";
-
-// Exit codes:
-const int kSuccessExitCode = 0;
-const int kUsageExitCode = 1;
-const int kErrorExitCode = 2;
-
-void usage(const char* program_name) {
- fprintf(stderr, kUsageMessage, program_name);
-}
-
-} // namespace
-
-namespace remoting {
-
-HostService::HostService() :
- console_session_id_(kInvalidSessionId),
- message_loop_(NULL),
- run_routine_(&HostService::RunAsService),
- service_name_(kWindowsServiceName),
- service_status_handle_(0),
- shutting_down_(false),
- stopped_event_(true, false) {
-}
-
-HostService::~HostService() {
-}
-
-void HostService::AddWtsConsoleObserver(WtsConsoleObserver* observer) {
- DCHECK(message_loop_->message_loop_proxy()->BelongsToCurrentThread());
-
- console_observers_.AddObserver(observer);
-}
-
-void HostService::RemoveWtsConsoleObserver(WtsConsoleObserver* observer) {
- DCHECK(message_loop_->message_loop_proxy()->BelongsToCurrentThread());
-
- console_observers_.RemoveObserver(observer);
-
- // Stop the service if there are no more observers.
- if (!console_observers_.might_have_observers()) {
- message_loop_->PostTask(FROM_HERE, MessageLoop::QuitClosure());
- }
-}
-
-void HostService::OnSessionChange() {
- // WTSGetActiveConsoleSessionId is a very cheap API. It basically reads
- // a single value from shared memory. Therefore it is better to check if
- // the console session is still the same every time a session change
- // notification event is posted. This also takes care of coalescing multiple
- // events into one since we look at the latest state.
- uint32 console_session_id = kInvalidSessionId;
- if (!shutting_down_) {
- console_session_id = WTSGetActiveConsoleSessionId();
- }
- if (console_session_id_ != console_session_id) {
- if (console_session_id_ != kInvalidSessionId) {
- FOR_EACH_OBSERVER(WtsConsoleObserver,
- console_observers_,
- OnSessionDetached());
- }
-
- console_session_id_ = console_session_id;
-
- if (console_session_id_ != kInvalidSessionId) {
- FOR_EACH_OBSERVER(WtsConsoleObserver,
- console_observers_,
- OnSessionAttached(console_session_id_));
- }
- }
-}
-
-BOOL WINAPI HostService::ConsoleControlHandler(DWORD event) {
- HostService* self = HostService::GetInstance();
- switch (event) {
- case CTRL_C_EVENT:
- case CTRL_BREAK_EVENT:
- case CTRL_CLOSE_EVENT:
- case CTRL_LOGOFF_EVENT:
- case CTRL_SHUTDOWN_EVENT:
- self->message_loop_->PostTask(FROM_HERE, MessageLoop::QuitClosure());
- self->stopped_event_.Wait();
- return TRUE;
-
- default:
- return FALSE;
- }
-}
-
-HostService* HostService::GetInstance() {
- return Singleton<HostService>::get();
-}
-
-bool HostService::InitWithCommandLine(const CommandLine* command_line) {
- CommandLine::StringVector args = command_line->GetArgs();
-
- // Choose the action to perform.
- if (!args.empty()) {
- if (args.size() > 1) {
- LOG(ERROR) << "Invalid command line: more than one action requested.";
- return false;
- }
- if (args[0] != kRunActionName) {
- LOG(ERROR) << "Invalid command line: invalid action specified: "
- << args[0];
- return false;
- }
- }
-
- if (command_line->HasSwitch(kHostBinarySwitchName)) {
- host_binary_ = command_line->GetSwitchValuePath(kHostBinarySwitchName);
- } else {
- LOG(ERROR) << "Invalid command line: --" << kHostBinarySwitchName
- << " is required.";
- return false;
- }
-
- // Run interactively if needed.
- if (run_routine_ == &HostService::RunAsService &&
- command_line->HasSwitch(kConsoleSwitchName)) {
- run_routine_ = &HostService::RunInConsole;
- }
-
- return true;
-}
-
-int HostService::Run() {
- return (this->*run_routine_)();
-}
-
-void HostService::RunMessageLoop() {
- // Launch the I/O thread.
- base::Thread io_thread(kIoThreadName);
- base::Thread::Options io_thread_options(MessageLoop::TYPE_IO, 0);
- if (!io_thread.StartWithOptions(io_thread_options)) {
- LOG(FATAL) << "Failed to start the I/O thread";
- shutting_down_ = true;
- stopped_event_.Signal();
- return;
- }
-
- WtsSessionProcessLauncher launcher(this, host_binary_,
- message_loop_->message_loop_proxy(),
- io_thread.message_loop_proxy());
-
- // Run the service.
- message_loop_->Run();
-
- // Clean up the observers by emulating detaching from the console.
- shutting_down_ = true;
- OnSessionChange();
-
- // Release the control handler.
- stopped_event_.Signal();
-}
-
-int HostService::RunAsService() {
- SERVICE_TABLE_ENTRYW dispatch_table[] = {
- { const_cast<LPWSTR>(service_name_.c_str()), &HostService::ServiceMain },
- { NULL, NULL }
- };
-
- if (!StartServiceCtrlDispatcherW(dispatch_table)) {
- LOG_GETLASTERROR(ERROR)
- << "Failed to connect to the service control manager";
- return kErrorExitCode;
- }
-
- return kSuccessExitCode;
-}
-
-int HostService::RunInConsole() {
- MessageLoop message_loop(MessageLoop::TYPE_UI);
-
- // Allow other threads to post to our message loop.
- message_loop_ = &message_loop;
-
- int result = kErrorExitCode;
-
- // Subscribe to Ctrl-C and other console events.
- if (!SetConsoleCtrlHandler(&HostService::ConsoleControlHandler, TRUE)) {
- LOG_GETLASTERROR(ERROR)
- << "Failed to set console control handler";
- return result;
- }
-
- // Create a window for receiving session change notifications.
- HWND window = NULL;
- WNDCLASSEX window_class;
- base::win::InitializeWindowClass(
- kSessionNotificationWindowClass,
- &base::win::WrappedWindowProc<SessionChangeNotificationProc>,
- 0, 0, 0, NULL, NULL, NULL, NULL, NULL,
- &window_class);
- HINSTANCE instance = window_class.hInstance;
- ATOM atom = RegisterClassExW(&window_class);
- if (atom == 0) {
- LOG_GETLASTERROR(ERROR)
- << "Failed to register the window class '"
- << kSessionNotificationWindowClass << "'";
- goto cleanup;
- }
-
- window = CreateWindowW(MAKEINTATOM(atom), 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0,
- instance, 0);
- if (window == NULL) {
- LOG_GETLASTERROR(ERROR)
- << "Failed to creat the session notificationwindow";
- goto cleanup;
- }
-
- // Post a dummy session change notification to peek up the current console
- // session.
- message_loop.PostTask(FROM_HERE, base::Bind(
- &HostService::OnSessionChange, base::Unretained(this)));
-
- // Subscribe to session change notifications.
- if (WTSRegisterSessionNotification(window,
- NOTIFY_FOR_ALL_SESSIONS) != FALSE) {
- // Run the service.
- RunMessageLoop();
-
- WTSUnRegisterSessionNotification(window);
- result = kSuccessExitCode;
- }
-
-cleanup:
- if (window != NULL) {
- DestroyWindow(window);
- }
-
- if (atom != 0) {
- UnregisterClass(MAKEINTATOM(atom), instance);
- }
-
- // Unsubscribe from console events. Ignore the exit code. There is nothing
- // we can do about it now and the program is about to exit anyway. Even if
- // it crashes nothing is going to be broken because of it.
- SetConsoleCtrlHandler(&HostService::ConsoleControlHandler, FALSE);
-
- message_loop_ = NULL;
- return result;
-}
-
-DWORD WINAPI HostService::ServiceControlHandler(DWORD control,
- DWORD event_type,
- LPVOID event_data,
- LPVOID context) {
- HostService* self = reinterpret_cast<HostService*>(context);
- switch (control) {
- case SERVICE_CONTROL_INTERROGATE:
- return NO_ERROR;
-
- case SERVICE_CONTROL_SHUTDOWN:
- case SERVICE_CONTROL_STOP:
- self->message_loop_->PostTask(FROM_HERE, MessageLoop::QuitClosure());
- self->stopped_event_.Wait();
- return NO_ERROR;
-
- case SERVICE_CONTROL_SESSIONCHANGE:
- self->message_loop_->PostTask(FROM_HERE, base::Bind(
- &HostService::OnSessionChange, base::Unretained(self)));
- return NO_ERROR;
-
- default:
- return ERROR_CALL_NOT_IMPLEMENTED;
- }
-}
-
-VOID WINAPI HostService::ServiceMain(DWORD argc, WCHAR* argv[]) {
- MessageLoop message_loop;
-
- // Allow other threads to post to our message loop.
- HostService* self = HostService::GetInstance();
- self->message_loop_ = &message_loop;
-
- // Register the service control handler.
- self->service_status_handle_ =
- RegisterServiceCtrlHandlerExW(self->service_name_.c_str(),
- &HostService::ServiceControlHandler,
- self);
- if (self->service_status_handle_ == 0) {
- LOG_GETLASTERROR(ERROR)
- << "Failed to register the service control handler";
- return;
- }
-
- // Report running status of the service.
- SERVICE_STATUS service_status;
- ZeroMemory(&service_status, sizeof(service_status));
- service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
- service_status.dwCurrentState = SERVICE_RUNNING;
- service_status.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN |
- SERVICE_ACCEPT_STOP |
- SERVICE_ACCEPT_SESSIONCHANGE;
- service_status.dwWin32ExitCode = kSuccessExitCode;
-
- if (!SetServiceStatus(self->service_status_handle_, &service_status)) {
- LOG_GETLASTERROR(ERROR)
- << "Failed to report service status to the service control manager";
- return;
- }
-
- // Post a dummy session change notification to peek up the current console
- // session.
- message_loop.PostTask(FROM_HERE, base::Bind(
- &HostService::OnSessionChange, base::Unretained(self)));
-
- // Run the service.
- self->RunMessageLoop();
-
- // Tell SCM that the service is stopped.
- service_status.dwCurrentState = SERVICE_STOPPED;
- service_status.dwControlsAccepted = 0;
-
- if (!SetServiceStatus(self->service_status_handle_, &service_status)) {
- LOG_GETLASTERROR(ERROR)
- << "Failed to report service status to the service control manager";
- return;
- }
-
- self->message_loop_ = NULL;
-}
-
-LRESULT CALLBACK HostService::SessionChangeNotificationProc(HWND hwnd,
- UINT message,
- WPARAM wparam,
- LPARAM lparam) {
- switch (message) {
- case WM_WTSSESSION_CHANGE: {
- HostService* self = HostService::GetInstance();
- self->OnSessionChange();
- return 0;
- }
-
- default:
- return DefWindowProc(hwnd, message, wparam, lparam);
- }
-}
-
-} // namespace remoting
-
-int main(int argc, char** argv) {
-#ifdef OFFICIAL_BUILD
- if (remoting::IsUsageStatsAllowed()) {
- remoting::InitializeCrashReporting();
- }
-#endif // OFFICIAL_BUILD
-
- CommandLine::Init(argc, argv);
-
- // This object instance is required by Chrome code (for example,
- // FilePath, LazyInstance, MessageLoop).
- base::AtExitManager exit_manager;
-
- // Write logs to the application profile directory.
- FilePath debug_log = remoting::GetConfigDir().
- Append(FILE_PATH_LITERAL("debug.log"));
- InitLogging(debug_log.value().c_str(),
- logging::LOG_ONLY_TO_FILE,
- logging::DONT_LOCK_LOG_FILE,
- logging::APPEND_TO_OLD_LOG_FILE,
- logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS);
-
- const CommandLine* command_line = CommandLine::ForCurrentProcess();
-
- if (command_line->HasSwitch(kHelpSwitchName) ||
- command_line->HasSwitch(kQuestionSwitchName)) {
- usage(argv[0]);
- return kSuccessExitCode;
- }
-
- remoting::HostService* service = remoting::HostService::GetInstance();
- if (!service->InitWithCommandLine(command_line)) {
- usage(argv[0]);
- return kUsageExitCode;
- }
-
- return service->Run();
-}
« no previous file with comments | « remoting/host/host_service_win.h ('k') | remoting/host/launch_process_in_session_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698