12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/host/win/wts_terminal_monitor.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <windows.h> 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <wtsapi32.h> 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/basictypes.h" 11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/logging.h" 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace remoting { 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Session id that does not represent any session. 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const uint32 kInvalidSessionId = 0xffffffffu; 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst char* WtsTerminalMonitor::kConsole = "console"; 20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WtsTerminalMonitor::~WtsTerminalMonitor() { 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool WtsTerminalMonitor::LookupTerminalId(uint32 session_id, 26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string* terminal_id) { 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Fast path for the case when |session_id| is currently attached to 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the physical console. 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (session_id == WTSGetActiveConsoleSessionId()) { 30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *terminal_id = kConsole; 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // RdpClient sets the terminal ID as the initial program's working directory. 35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DWORD bytes; 36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch wchar_t* working_directory; 37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, 38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_id, 39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch WTSWorkingDirectory, 40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &working_directory, 41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &bytes)) { 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool result = WideToUTF8(working_directory, (bytes / sizeof(wchar_t)) - 1, 46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch terminal_id); 47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch WTSFreeMemory(working_directory); 48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return result; 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochuint32 WtsTerminalMonitor::LookupSessionId(const std::string& terminal_id) { 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Use the fast path if the caller wants to get id of the session attached to 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the physical console. 55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (terminal_id == kConsole) 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return WTSGetActiveConsoleSessionId(); 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Enumerate all sessions and try to match the client endpoint. 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WTS_SESSION_INFO* session_info; 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DWORD session_info_count; 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &session_info, 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &session_info_count)) { 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG_GETLASTERROR(ERROR) << "Failed to enumerate all sessions"; 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return kInvalidSessionId; 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (DWORD i = 0; i < session_info_count; ++i) { 67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch uint32 session_id = session_info[i].SessionId; 68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string id; 70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (LookupTerminalId(session_id, &id) && terminal_id == id) { 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WTSFreeMemory(session_info); 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return session_id; 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // |terminal_id| is not associated with any session. 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WTSFreeMemory(session_info); 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return kInvalidSessionId; 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WtsTerminalMonitor::WtsTerminalMonitor() { 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace remoting 85