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