1// Copyright (c) 2013 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#ifndef REMOTING_HOST_WIN_RDP_HOST_WINDOW_H_
6#define REMOTING_HOST_WIN_RDP_HOST_WINDOW_H_
7
8#include <atlbase.h>
9#include <atlcom.h>
10#include <atlcrack.h>
11#include <atlctl.h>
12
13#include "base/basictypes.h"
14#include "base/memory/ref_counted.h"
15#include "base/message_loop/message_loop.h"
16#include "base/win/scoped_comptr.h"
17#include "net/base/ip_endpoint.h"
18#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
19
20#import "PROGID:MsTscAx.MsTscAx" \
21    exclude("wireHWND", "_RemotableHandle", "__MIDL_IWinTypes_0009"), \
22    rename_namespace("mstsc") raw_interfaces_only no_implementation
23
24namespace remoting {
25
26// RdpClientWindow is used to establish a connection to the given RDP endpoint.
27// It is a GUI window class that hosts Microsoft RDP ActiveX control, which
28// takes care of handling RDP properly. RdpClientWindow must be used only on
29// a UI thread.
30class RdpClientWindow
31    : public CWindowImpl<RdpClientWindow, CWindow, CFrameWinTraits>,
32      public IDispEventImpl<1, RdpClientWindow,
33                            &__uuidof(mstsc::IMsTscAxEvents),
34                            &__uuidof(mstsc::__MSTSCLib), 1, 0> {
35 public:
36  // Receives connect/disconnect notifications. The notifications can be
37  // delivered after RdpClientWindow::Connect() returned success.
38  //
39  // RdpClientWindow guarantees that OnDisconnected() is the last notification
40  // the event handler receives. OnDisconnected() is guaranteed to be called
41  // only once.
42  class EventHandler {
43   public:
44    virtual ~EventHandler() {}
45
46    // Invoked when the RDP control has established a connection.
47    virtual void OnConnected() = 0;
48
49    // Invoked when the RDP control has been disconnected from the RDP server.
50    // This includes both graceful shutdown and any fatal error condition.
51    //
52    // Once RdpClientWindow::Connect() returns success the owner of the
53    // |RdpClientWindow| object must keep it alive until OnDisconnected() is
54    // called.
55    //
56    // OnDisconnected() should not delete |RdpClientWindow| object directly.
57    // Instead it should post a task to delete the object. The ActiveX code
58    // expects the window be alive until the currently handled window message is
59    // completely processed.
60    virtual void OnDisconnected() = 0;
61  };
62
63  DECLARE_WND_CLASS(L"RdpClientWindow")
64
65  // Specifies the endpoint to connect to and passes the event handler pointer
66  // to be notified about connection events.
67  RdpClientWindow(const net::IPEndPoint& server_endpoint,
68                  const std::string& terminal_id,
69                  EventHandler* event_handler);
70  ~RdpClientWindow();
71
72  // Creates the window along with the ActiveX control and initiates the
73  // connection. |screen_size| specifies resolution of the screen. Returns false
74  // if an error occurs.
75  bool Connect(const webrtc::DesktopSize& screen_size);
76
77  // Initiates shutdown of the connection. The caller must not delete |this|
78  // until it receives OnDisconnected() notification.
79  void Disconnect();
80
81  // Emulates pressing Ctrl+Alt+End combination that is translated to Secure
82  // Attention Sequence by the ActiveX control.
83  void InjectSas();
84
85 private:
86  typedef IDispEventImpl<1, RdpClientWindow,
87                         &__uuidof(mstsc::IMsTscAxEvents),
88                         &__uuidof(mstsc::__MSTSCLib), 1, 0> RdpEventsSink;
89
90  // Handled window messages.
91  BEGIN_MSG_MAP_EX(RdpClientWindow)
92    MSG_WM_CLOSE(OnClose)
93    MSG_WM_CREATE(OnCreate)
94    MSG_WM_DESTROY(OnDestroy)
95  END_MSG_MAP()
96
97  // Requests the RDP ActiveX control to close the connection gracefully.
98  void OnClose();
99
100  // Creates the RDP ActiveX control, configures it, and initiates an RDP
101  // connection to |server_endpoint_|.
102  LRESULT OnCreate(CREATESTRUCT* create_struct);
103
104  // Releases the RDP ActiveX control interfaces.
105  void OnDestroy();
106
107  BEGIN_SINK_MAP(RdpClientWindow)
108    SINK_ENTRY_EX(1, __uuidof(mstsc::IMsTscAxEvents), 2, OnConnected)
109    SINK_ENTRY_EX(1, __uuidof(mstsc::IMsTscAxEvents), 4, OnDisconnected)
110    SINK_ENTRY_EX(1, __uuidof(mstsc::IMsTscAxEvents), 10, OnFatalError)
111    SINK_ENTRY_EX(1, __uuidof(mstsc::IMsTscAxEvents), 15, OnConfirmClose)
112    SINK_ENTRY_EX(1, __uuidof(mstsc::IMsTscAxEvents), 18,
113                  OnAuthenticationWarningDisplayed)
114    SINK_ENTRY_EX(1, __uuidof(mstsc::IMsTscAxEvents), 19,
115                  OnAuthenticationWarningDismissed)
116  END_SINK_MAP()
117
118  // mstsc::IMsTscAxEvents notifications.
119  STDMETHOD(OnAuthenticationWarningDisplayed)();
120  STDMETHOD(OnAuthenticationWarningDismissed)();
121  STDMETHOD(OnConnected)();
122  STDMETHOD(OnDisconnected)(long reason);
123  STDMETHOD(OnFatalError)(long error_code);
124  STDMETHOD(OnConfirmClose)(VARIANT_BOOL* allow_close);
125
126  // Wrappers for the event handler's methods that make sure that
127  // OnDisconnected() is the last notification delivered and is delevered
128  // only once.
129  void NotifyConnected();
130  void NotifyDisconnected();
131
132  // Invoked to report connect/disconnect events.
133  EventHandler* event_handler_;
134
135  // Contains the requested dimensions of the screen.
136  webrtc::DesktopSize screen_size_;
137
138  // The endpoint to connect to.
139  net::IPEndPoint server_endpoint_;
140
141  // The terminal ID assigned to this connection.
142  std::string terminal_id_;
143
144  // Interfaces exposed by the RDP ActiveX control.
145  base::win::ScopedComPtr<mstsc::IMsRdpClient> client_;
146  base::win::ScopedComPtr<mstsc::IMsRdpClientAdvancedSettings> client_settings_;
147
148  // Used to cancel modal dialog boxes shown by the RDP control.
149  class WindowHook;
150  scoped_refptr<WindowHook> window_activate_hook_;
151};
152
153}  // namespace remoting
154
155#endif  // REMOTING_HOST_WIN_RDP_HOST_WINDOW_H_
156