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