12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 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)#ifndef REMOTING_HOST_WIN_RDP_HOST_WINDOW_H_
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define REMOTING_HOST_WIN_RDP_HOST_WINDOW_H_
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <atlbase.h>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <atlcom.h>
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <atlcrack.h>
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <atlctl.h>
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/basictypes.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/memory/ref_counted.h"
159ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/win/scoped_comptr.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/ip_endpoint.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// The following header was generated by Visual Studio. We had to check it in
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// due to a bug in VS2013. See crbug.com/318952 for details.
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "remoting/host/win/com_imported_mstscax.tlh"
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace remoting {
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// RdpClientWindow is used to establish a connection to the given RDP endpoint.
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// It is a GUI window class that hosts Microsoft RDP ActiveX control, which
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// takes care of handling RDP properly. RdpClientWindow must be used only on
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// a UI thread.
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class RdpClientWindow
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public CWindowImpl<RdpClientWindow, CWindow, CFrameWinTraits>,
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      public IDispEventImpl<1, RdpClientWindow,
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            &__uuidof(mstsc::IMsTscAxEvents),
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            &__uuidof(mstsc::__MSTSCLib), 1, 0> {
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Receives connect/disconnect notifications. The notifications can be
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // delivered after RdpClientWindow::Connect() returned success.
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // RdpClientWindow guarantees that OnDisconnected() is the last notification
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the event handler receives. OnDisconnected() is guaranteed to be called
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // only once.
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  class EventHandler {
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   public:
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    virtual ~EventHandler() {}
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Invoked when the RDP control has established a connection.
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    virtual void OnConnected() = 0;
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Invoked when the RDP control has been disconnected from the RDP server.
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // This includes both graceful shutdown and any fatal error condition.
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    //
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Once RdpClientWindow::Connect() returns success the owner of the
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // |RdpClientWindow| object must keep it alive until OnDisconnected() is
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // called.
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    //
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // OnDisconnected() should not delete |RdpClientWindow| object directly.
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Instead it should post a task to delete the object. The ActiveX code
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // expects the window be alive until the currently handled window message is
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // completely processed.
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    virtual void OnDisconnected() = 0;
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DECLARE_WND_CLASS(L"RdpClientWindow")
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Specifies the endpoint to connect to and passes the event handler pointer
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to be notified about connection events.
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RdpClientWindow(const net::IPEndPoint& server_endpoint,
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                  const std::string& terminal_id,
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  EventHandler* event_handler);
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ~RdpClientWindow();
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Creates the window along with the ActiveX control and initiates the
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // connection. |screen_size| specifies resolution of the screen. Returns false
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // if an error occurs.
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool Connect(const webrtc::DesktopSize& screen_size);
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Initiates shutdown of the connection. The caller must not delete |this|
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // until it receives OnDisconnected() notification.
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Disconnect();
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Emulates pressing Ctrl+Alt+End combination that is translated to Secure
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Attention Sequence by the ActiveX control.
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void InjectSas();
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef IDispEventImpl<1, RdpClientWindow,
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         &__uuidof(mstsc::IMsTscAxEvents),
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         &__uuidof(mstsc::__MSTSCLib), 1, 0> RdpEventsSink;
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Handled window messages.
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BEGIN_MSG_MAP_EX(RdpClientWindow)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MSG_WM_CLOSE(OnClose)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MSG_WM_CREATE(OnCreate)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MSG_WM_DESTROY(OnDestroy)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  END_MSG_MAP()
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Requests the RDP ActiveX control to close the connection gracefully.
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnClose();
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Creates the RDP ActiveX control, configures it, and initiates an RDP
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // connection to |server_endpoint_|.
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LRESULT OnCreate(CREATESTRUCT* create_struct);
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Releases the RDP ActiveX control interfaces.
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnDestroy();
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BEGIN_SINK_MAP(RdpClientWindow)
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    SINK_ENTRY_EX(1, __uuidof(mstsc::IMsTscAxEvents), 2,
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  &RdpClientWindow::OnConnected)
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    SINK_ENTRY_EX(1, __uuidof(mstsc::IMsTscAxEvents), 4,
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  &RdpClientWindow::OnDisconnected)
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    SINK_ENTRY_EX(1, __uuidof(mstsc::IMsTscAxEvents), 10,
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  &RdpClientWindow::OnFatalError)
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    SINK_ENTRY_EX(1, __uuidof(mstsc::IMsTscAxEvents), 15,
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  &RdpClientWindow::OnConfirmClose)
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SINK_ENTRY_EX(1, __uuidof(mstsc::IMsTscAxEvents), 18,
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  &RdpClientWindow::OnAuthenticationWarningDisplayed)
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SINK_ENTRY_EX(1, __uuidof(mstsc::IMsTscAxEvents), 19,
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  &RdpClientWindow::OnAuthenticationWarningDismissed)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  END_SINK_MAP()
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // mstsc::IMsTscAxEvents notifications.
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  STDMETHOD(OnAuthenticationWarningDisplayed)();
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  STDMETHOD(OnAuthenticationWarningDismissed)();
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STDMETHOD(OnConnected)();
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STDMETHOD(OnDisconnected)(long reason);
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STDMETHOD(OnFatalError)(long error_code);
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STDMETHOD(OnConfirmClose)(VARIANT_BOOL* allow_close);
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Wrappers for the event handler's methods that make sure that
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // OnDisconnected() is the last notification delivered and is delevered
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // only once.
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void NotifyConnected();
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void NotifyDisconnected();
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Invoked to report connect/disconnect events.
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EventHandler* event_handler_;
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Contains the requested dimensions of the screen.
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  webrtc::DesktopSize screen_size_;
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The endpoint to connect to.
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::IPEndPoint server_endpoint_;
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // The terminal ID assigned to this connection.
145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string terminal_id_;
146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Interfaces exposed by the RDP ActiveX control.
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::win::ScopedComPtr<mstsc::IMsRdpClient> client_;
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::win::ScopedComPtr<mstsc::IMsRdpClientAdvancedSettings> client_settings_;
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Used to cancel modal dialog boxes shown by the RDP control.
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  class WindowHook;
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<WindowHook> window_activate_hook_;
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace remoting
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // REMOTING_HOST_WIN_RDP_HOST_WINDOW_H_
159