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 3 // found in the LICENSE file. 4 5 #include "remoting/host/win/wts_terminal_monitor.h" 6 7 #include <windows.h> 8 #include <wtsapi32.h> 9 10 #include "base/basictypes.h" 11 #include "base/logging.h" 12 #include "base/strings/utf_string_conversions.h" 13 14 namespace remoting { 15 16 // Session id that does not represent any session. 17 const uint32 kInvalidSessionId = 0xffffffffu; 18 19 const char* WtsTerminalMonitor::kConsole = "console"; 20 21 WtsTerminalMonitor::~WtsTerminalMonitor() { 22 } 23 24 // static 25 bool WtsTerminalMonitor::LookupTerminalId(uint32 session_id, 26 std::string* terminal_id) { 27 // Fast path for the case when |session_id| is currently attached to 28 // the physical console. 29 if (session_id == WTSGetActiveConsoleSessionId()) { 30 *terminal_id = kConsole; 31 return true; 32 } 33 34 // RdpClient sets the terminal ID as the initial program's working directory. 35 DWORD bytes; 36 wchar_t* working_directory; 37 if (!WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, 38 session_id, 39 WTSWorkingDirectory, 40 &working_directory, 41 &bytes)) { 42 return false; 43 } 44 45 bool result = base::WideToUTF8(working_directory, 46 (bytes / sizeof(wchar_t)) - 1, 47 terminal_id); 48 WTSFreeMemory(working_directory); 49 return result; 50 } 51 52 // static 53 uint32 WtsTerminalMonitor::LookupSessionId(const std::string& terminal_id) { 54 // Use the fast path if the caller wants to get id of the session attached to 55 // the physical console. 56 if (terminal_id == kConsole) 57 return WTSGetActiveConsoleSessionId(); 58 59 // Enumerate all sessions and try to match the client endpoint. 60 WTS_SESSION_INFO* session_info; 61 DWORD session_info_count; 62 if (!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &session_info, 63 &session_info_count)) { 64 PLOG(ERROR) << "Failed to enumerate all sessions"; 65 return kInvalidSessionId; 66 } 67 for (DWORD i = 0; i < session_info_count; ++i) { 68 uint32 session_id = session_info[i].SessionId; 69 70 std::string id; 71 if (LookupTerminalId(session_id, &id) && terminal_id == id) { 72 WTSFreeMemory(session_info); 73 return session_id; 74 } 75 } 76 77 // |terminal_id| is not associated with any session. 78 WTSFreeMemory(session_info); 79 return kInvalidSessionId; 80 } 81 82 WtsTerminalMonitor::WtsTerminalMonitor() { 83 } 84 85 } // namespace remoting 86