rdp_client_window.h revision 9ab5563a3196760eb381d102cbb2bc0f7abc6a50
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"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/core/SkSize.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#import "PROGID:MsTscAx.MsTscAx" \
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    exclude("wireHWND", "_RemotableHandle", "__MIDL_IWinTypes_0009"), \
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rename_namespace("mstsc") raw_interfaces_only no_implementation
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace remoting {
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// RdpClientWindow is used to establish a connection to the given RDP endpoint.
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// It is a GUI window class that hosts Microsoft RDP ActiveX control, which
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// takes care of handling RDP properly. RdpClientWindow must be used only on
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// a UI thread.
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class RdpClientWindow
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public CWindowImpl<RdpClientWindow, CWindow, CFrameWinTraits>,
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      public IDispEventImpl<1, RdpClientWindow,
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            &__uuidof(mstsc::IMsTscAxEvents),
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            &__uuidof(mstsc::__MSTSCLib), 1, 0> {
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Receives connect/disconnect notifications. The notifications can be
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // delivered after RdpClientWindow::Connect() returned success.
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // RdpClientWindow guarantees that OnDisconnected() is the last notification
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the event handler receives. OnDisconnected() is guaranteed to be called
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // only once.
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  class EventHandler {
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   public:
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    virtual ~EventHandler() {}
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Invoked when the RDP control has established a connection.
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    virtual void OnConnected() = 0;
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Invoked when the RDP control has been disconnected from the RDP server.
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // This includes both graceful shutdown and any fatal error condition.
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    //
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Once RdpClientWindow::Connect() returns success the owner of the
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // |RdpClientWindow| object must keep it alive until OnDisconnected() is
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // called.
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    //
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // OnDisconnected() should not delete |RdpClientWindow| object directly.
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Instead it should post a task to delete the object. The ActiveX code
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // expects the window be alive until the currently handled window message is
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // completely processed.
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    virtual void OnDisconnected() = 0;
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DECLARE_WND_CLASS(L"RdpClientWindow")
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Specifies the endpoint to connect to and passes the event handler pointer
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to be notified about connection events.
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RdpClientWindow(const net::IPEndPoint& server_endpoint,
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                  const std::string& terminal_id,
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  EventHandler* event_handler);
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ~RdpClientWindow();
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Creates the window along with the ActiveX control and initiates the
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // connection. |screen_size| specifies resolution of the screen. Returns false
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // if an error occurs.
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool Connect(const SkISize& screen_size);
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Initiates shutdown of the connection. The caller must not delete |this|
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // until it receives OnDisconnected() notification.
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Disconnect();
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Emulates pressing Ctrl+Alt+End combination that is translated to Secure
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Attention Sequence by the ActiveX control.
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void InjectSas();
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef IDispEventImpl<1, RdpClientWindow,
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         &__uuidof(mstsc::IMsTscAxEvents),
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         &__uuidof(mstsc::__MSTSCLib), 1, 0> RdpEventsSink;
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Handled window messages.
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BEGIN_MSG_MAP_EX(RdpClientWindow)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MSG_WM_CLOSE(OnClose)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MSG_WM_CREATE(OnCreate)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MSG_WM_DESTROY(OnDestroy)
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  END_MSG_MAP()
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Requests the RDP ActiveX control to close the connection gracefully.
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnClose();
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Creates the RDP ActiveX control, configures it, and initiates an RDP
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // connection to |server_endpoint_|.
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LRESULT OnCreate(CREATESTRUCT* create_struct);
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Releases the RDP ActiveX control interfaces.
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnDestroy();
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BEGIN_SINK_MAP(RdpClientWindow)
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SINK_ENTRY_EX(1, __uuidof(mstsc::IMsTscAxEvents), 2, OnConnected)
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SINK_ENTRY_EX(1, __uuidof(mstsc::IMsTscAxEvents), 4, OnDisconnected)
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SINK_ENTRY_EX(1, __uuidof(mstsc::IMsTscAxEvents), 10, OnFatalError)
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SINK_ENTRY_EX(1, __uuidof(mstsc::IMsTscAxEvents), 15, OnConfirmClose)
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SINK_ENTRY_EX(1, __uuidof(mstsc::IMsTscAxEvents), 18,
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                  OnAuthenticationWarningDisplayed)
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SINK_ENTRY_EX(1, __uuidof(mstsc::IMsTscAxEvents), 19,
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                  OnAuthenticationWarningDismissed)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  END_SINK_MAP()
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // mstsc::IMsTscAxEvents notifications.
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  STDMETHOD(OnAuthenticationWarningDisplayed)();
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  STDMETHOD(OnAuthenticationWarningDismissed)();
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STDMETHOD(OnConnected)();
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STDMETHOD(OnDisconnected)(long reason);
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STDMETHOD(OnFatalError)(long error_code);
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STDMETHOD(OnConfirmClose)(VARIANT_BOOL* allow_close);
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Wrappers for the event handler's methods that make sure that
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // OnDisconnected() is the last notification delivered and is delevered
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // only once.
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void NotifyConnected();
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void NotifyDisconnected();
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Invoked to report connect/disconnect events.
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EventHandler* event_handler_;
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Contains the requested dimensions of the screen.
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkISize screen_size_;
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The endpoint to connect to.
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::IPEndPoint server_endpoint_;
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // The terminal ID assigned to this connection.
142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string terminal_id_;
143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Interfaces exposed by the RDP ActiveX control.
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::win::ScopedComPtr<mstsc::IMsRdpClient> client_;
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::win::ScopedComPtr<mstsc::IMsRdpClientAdvancedSettings> client_settings_;
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Used to cancel modal dialog boxes shown by the RDP control.
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  class WindowHook;
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<WindowHook> window_activate_hook_;
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace remoting
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // REMOTING_HOST_WIN_RDP_HOST_WINDOW_H_
156