diff options
author | alexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-01 10:15:09 +0000 |
---|---|---|
committer | alexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-01 10:15:09 +0000 |
commit | 0b205e16eeaa51a32b544687e08ef356d500245a (patch) | |
tree | 93ae9bf8cd5b0ec91e41c8398b314ab95ade6a7f /remoting | |
parent | 61e77c687ad8601cd64164d3191425400f7bc72c (diff) | |
download | chromium_src-0b205e16eeaa51a32b544687e08ef356d500245a.zip chromium_src-0b205e16eeaa51a32b544687e08ef356d500245a.tar.gz chromium_src-0b205e16eeaa51a32b544687e08ef356d500245a.tar.bz2 |
Introducing an out-of-process COM class hosting RdpClient.
RdpClient takes dependency on mstscax.dll that pulls a lot of code to the process. This CL allows RdpClient objects to be hosted in a separate process running at medium integrity level under LocalService account.
BUG=137696
Review URL: https://chromiumcodereview.appspot.com/12330178
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@185515 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
-rw-r--r-- | remoting/host/host_main.cc | 4 | ||||
-rw-r--r-- | remoting/host/host_main.h | 1 | ||||
-rw-r--r-- | remoting/host/installer/win/chromoting.wxs | 103 | ||||
-rw-r--r-- | remoting/host/installer/win/parameters.json | 1 | ||||
-rw-r--r-- | remoting/host/setup/daemon_controller_win.cc | 2 | ||||
-rw-r--r-- | remoting/host/win/chromoting_lib_idl.templ | 57 | ||||
-rw-r--r-- | remoting/host/win/chromoting_module.cc | 70 | ||||
-rw-r--r-- | remoting/host/win/chromoting_module.h | 2 | ||||
-rw-r--r-- | remoting/host/win/elevated_controller.h | 10 | ||||
-rw-r--r-- | remoting/host/win/rdp_client.cc | 17 | ||||
-rw-r--r-- | remoting/host/win/rdp_client.h | 2 | ||||
-rw-r--r-- | remoting/host/win/rdp_client_unittest.cc | 7 | ||||
-rw-r--r-- | remoting/host/win/rdp_desktop_session.cc | 56 | ||||
-rw-r--r-- | remoting/host/win/rdp_desktop_session.h | 76 | ||||
-rw-r--r-- | remoting/remoting.gyp | 14 |
15 files changed, 391 insertions, 31 deletions
diff --git a/remoting/host/host_main.cc b/remoting/host/host_main.cc index 96b2752..1687758 100644 --- a/remoting/host/host_main.cc +++ b/remoting/host/host_main.cc @@ -42,6 +42,7 @@ int DesktopProcessMain(); #if defined(OS_WIN) int ElevatedControllerMain(); +int RdpDesktopSessionMain(); #endif // defined(OS_WIN) const char kElevateSwitchName[] = "elevate"; @@ -56,6 +57,7 @@ const char kProcessTypeDesktop[] = "desktop"; #if defined(OS_WIN) const char kProcessTypeController[] = "controller"; +const char kProcessTypeRdpDesktopSession[] = "rdp_desktop_session"; #endif // defined(OS_WIN) namespace { @@ -146,6 +148,8 @@ MainRoutineFn SelectMainRoutine(const std::string& process_type) { #if defined(OS_WIN) if (process_type == kProcessTypeController) { main_routine = &ElevatedControllerMain; + } else if (process_type == kProcessTypeRdpDesktopSession) { + main_routine = &RdpDesktopSessionMain; } #endif // defined(OS_WIN) diff --git a/remoting/host/host_main.h b/remoting/host/host_main.h index 5dbdd35..2b56734 100644 --- a/remoting/host/host_main.h +++ b/remoting/host/host_main.h @@ -25,6 +25,7 @@ extern const char kProcessTypeDesktop[]; #if defined(OS_WIN) extern const char kProcessTypeController[]; +extern const char kProcessTypeRdpDesktopSession[]; #endif // defined(OS_WIN) // The common entry point exported from remoting_core.dll. It uses diff --git a/remoting/host/installer/win/chromoting.wxs b/remoting/host/installer/win/chromoting.wxs index 0ef21fd..a88b4a40 100644 --- a/remoting/host/installer/win/chromoting.wxs +++ b/remoting/host/installer/win/chromoting.wxs @@ -28,29 +28,51 @@ <?define ChromotingTypelib = "{b6396c45-b0cc-456b-9f49-f12964ee6df4}" ?> + <!-- AppIDs used by the COM components. --> <?define ControllerAppid = "{4ff35d5e-d226-4550-9248-03e7779e67de}" ?> + <?define RdpAppid = "{52e6fd1a-f16e-49c0-aacb-5436a915448b}" ?> + <?define ControllerClass = "ElevatedController Class" ?> <?define ControllerProgid = "ChromotingElevatedController.ElevatedController" ?> <!-- - The long hex value below is a security descriptor that allows SYSTEM, - built-in administrators and interactive users to call methods of a COM - object (COM_RIGHTS_EXECUTE and COM_RIGHTS_EXECUTE_LOCAL). The security - descriptor was generated from SDDL definition using the PowerShell script - below: - - $sddl = "O:BAG:BAD:(A;;0x3;;;IU)(A;;0x3;;;SY)(A;;0x3;;;BA)" - $i = ([wmiclass]"Win32_SecurityDescriptorHelper").SDDLToBinarySD($sddl).BinarySD - -join ($i | foreach {$_.ToString("X2")}) + The long hex values below are security descriptors generated from SDDL + definition using the PowerShell script below: + + $sddl = "<SDDL definition goes here>" + $i = ([wmiclass]"Win32_SecurityDescriptorHelper").SDDLToBinarySD($sddl).BinarySD + -join ($i | foreach {$_.ToString("X2")}) + --> + + <!-- + A security descriptor that allows SYSTEM, built-in administrators and + interactive users COM_RIGHTS_EXECUTE and COM_RIGHTS_EXECUTE_LOCAL rights. + The SDDL definition: + + $sddl = "O:BAG:BAD:(A;;0x3;;;IU)(A;;0x3;;;SY)(A;;0x3;;;BA)" --> <?define ControllerSd = "010004805C0000006C00000000000000140000000200480003000000000014000300000001010000000000050400000000001400030000000101000000000005120000000000180003000000010200000000000520000000200200000102000000000005200000002002000001020000000000052000000020020000" ?> + <!-- + A security descriptor that gives SYSTEM, built-in administrators and + LocalSystem accounts COM_RIGHTS_EXECUTE, COM_RIGHTS_EXECUTE_LOCAL, and + COM_RIGHTS_ACTIVATE_LOCAL rights. It specifies a mandatory label that + specifies "no execute up" policy for medium integrity level. + + $sddl = "O:BAG:BAD:(A;;0xb;;;SY)(A;;0xb;;;BA)(A;;0xb;;;LS)S:(ML;;NX;;;ME)" + --> + <?define RdpSd = "010014807800000088000000140000003000000002001C000100000011001400040000000101000000000010002000000200480003000000000014000B000000010100000000000512000000000018000B00000001020000000000052000000020020000000014000B0000000101000000000005130000000102000000000005200000002002000001020000000000052000000020020000" ?> + <!-- Verify that all required parameters are defined. --> <?ifndef ControllerClsid ?> <?error ControllerClsid must be defined ?> <?endif?> + <?ifndef RdpDesktopSessionClsid ?> + <?error RdpDesktopSessionClsid must be defined ?> + <?endif?> + <?ifndef Version ?> <?error Version must be defined ?> <?endif?> @@ -238,6 +260,21 @@ Type="binary" Value="$(var.ControllerSd)"/> </RegistryKey> + + <RegistryKey Key="$(var.RdpAppid)" Action="create"> + <RegistryValue Type="string" + Value="ChromotingRdpDesktopSession"/> + <RegistryValue Name="AccessPermission" + Type="binary" + Value="$(var.RdpSd)"/> + <RegistryValue Name="LaunchPermission" + Type="binary" + Value="$(var.RdpSd)"/> + <RegistryValue Name="RunAs" + Type="string" + Value="NT AUTHORITY\LocalService"/> + </RegistryKey> + </RegistryKey> <RegistryKey Key="$(var.ControllerProgid)" Action="create"> @@ -308,9 +345,42 @@ Value="@[binaries]$(var.CoreBinary),-104"/> </RegistryKey> </RegistryKey> + <RegistryKey Key="$(var.RdpDesktopSessionClsid)" Action="create"> + <RegistryValue Type="string" + Value="RdpDesktopSession Class"/> + + <RegistryValue Type="string" + Name="AppID" + Value="$(var.RdpAppid)"/> + + <RegistryKey Key="LocalServer32" Action="create"> + <RegistryValue Type="string" + Value="[binaries]$(var.HostBinary) --type=rdp_desktop_session"/> + </RegistryKey> + + <RegistryKey Key="TypeLib" Action="create"> + <RegistryValue Type="string" + Value="$(var.ChromotingTypelib)"/> + </RegistryKey> + </RegistryKey> </RegistryKey> <RegistryKey Key="Interface"> + <!-- IRdpDesktopSession interface --> + <RegistryKey Key="{126c22bc-34ef-4cfb-83ef-9b8ada3391e8}" + Action="create"> + <RegistryKey Key="ProxyStubClsid32" Action="create"> + <RegistryValue Type="string" + Value="{00020424-0000-0000-C000-000000000046}"/> + </RegistryKey> + + <RegistryKey Key="TypeLib" Action="create"> + <RegistryValue Type="string" + Value="$(var.ChromotingTypelib)"/> + </RegistryKey> + </RegistryKey> + + <!-- IDaemonControl2 interface --> <RegistryKey Key="{655bd819-c08c-4b04-80c2-f160739ff6ef}" Action="create"> <RegistryKey Key="ProxyStubClsid32" Action="create"> @@ -324,6 +394,21 @@ </RegistryKey> </RegistryKey> + <!-- IRdpDesktopSessionEventHandler interface --> + <RegistryKey Key="{987bca97-9d40-42fc-a00d-e6a701261af5}" + Action="create"> + <RegistryKey Key="ProxyStubClsid32" Action="create"> + <RegistryValue Type="string" + Value="{00020424-0000-0000-C000-000000000046}"/> + </RegistryKey> + + <RegistryKey Key="TypeLib" Action="create"> + <RegistryValue Type="string" + Value="$(var.ChromotingTypelib)"/> + </RegistryKey> + </RegistryKey> + + <!-- IDaemonControl interface --> <RegistryKey Key="{e051a481-6345-4ba1-bdb1-cf7929955268}" Action="create"> <RegistryKey Key="ProxyStubClsid32" Action="create"> diff --git a/remoting/host/installer/win/parameters.json b/remoting/host/installer/win/parameters.json index 324dc7e..e044343 100644 --- a/remoting/host/installer/win/parameters.json +++ b/remoting/host/installer/win/parameters.json @@ -3,6 +3,7 @@ "Branding": "@@BRANDING@@", "ControllerClsid": "@@DAEMON_CONTROLLER_CLSID@@", "OfficialBuild": "@@OFFICIAL_BUILD@@", + "RdpDesktopSessionClsid": "@@RDP_DESKTOP_SESSION_CLSID@@", "RemotingMultiProcess" : "@@REMOTING_MULTI_PROCESS@@", "Version": "@@VERSION@@" }, diff --git a/remoting/host/setup/daemon_controller_win.cc b/remoting/host/setup/daemon_controller_win.cc index 497fd5a..dfcc373 100644 --- a/remoting/host/setup/daemon_controller_win.cc +++ b/remoting/host/setup/daemon_controller_win.cc @@ -26,7 +26,7 @@ #include "base/win/windows_version.h" #include "remoting/base/scoped_sc_handle_win.h" #include "remoting/host/branding.h" -// MIDL-generated declarations and definitions. +// chromoting_lib.h contains MIDL-generated declarations. #include "remoting/host/chromoting_lib.h" #include "remoting/host/setup/daemon_installer_win.h" #include "remoting/host/usage_stats_consent.h" diff --git a/remoting/host/win/chromoting_lib_idl.templ b/remoting/host/win/chromoting_lib_idl.templ index f2f7f31..c5b496c 100644 --- a/remoting/host/win/chromoting_lib_idl.templ +++ b/remoting/host/win/chromoting_lib_idl.templ @@ -13,7 +13,7 @@ import "ocidl.idl"; helpstring("IDaemonControl Interface"), pointer_default(unique) ] -interface IDaemonControl: IDispatch { +interface IDaemonControl : IDispatch { [ id(1), helpstring("Returns a filtered copy of the daemon's configuration. " "Only 'host_id' and 'xmpp_login' values are returned, " "because any other values may contain security-sensitive " @@ -53,7 +53,7 @@ interface IDaemonControl: IDispatch { helpstring("IDaemonControl2 Interface"), pointer_default(unique) ] -interface IDaemonControl2: IDaemonControl { +interface IDaemonControl2 : IDaemonControl { [ id(8), helpstring("Retrieves the user's consent to collect crash dumps " "and gather usage statistics.") ] HRESULT GetUsageStatsConsent([out] BOOL* allowed, @@ -65,6 +65,51 @@ interface IDaemonControl2: IDaemonControl { }; [ + object, + uuid(987bca97-9d40-42fc-a00d-e6a701261af5), + dual, + nonextensible, + helpstring("IRdpDesktopSessionEventHandler Interface"), + pointer_default(unique) +] +interface IRdpDesktopSessionEventHandler : IDispatch { + [ id(1), helpstring("Notifies that an RDP connection has been established " + "successfully. The client's address and port are " + " returned in |client_endpoint| as |SOCKADDR_STORAGE| " + "structure. When this method is called multiple times, " + "the most recent |client_endpoint| supersedes all " + "previous ones.") ] + HRESULT OnRdpConnected([in, size_is(length)] byte* client_endpoint, + [in] long length); + + [ id(2), helpstring("Notifies the delegate that the RDP connection has been " + "closed.") ] + HRESULT OnRdpClosed(); +}; + +[ + object, + uuid(126c22bc-34ef-4cfb-83ef-9b8ada3391e8), + dual, + nonextensible, + helpstring("IRdpDesktopSession Interface"), + pointer_default(unique) +] +interface IRdpDesktopSession : IDispatch { + [ id(1), helpstring("Initiates a loopback RDP connection to spawn a new " + "Windows session. |width| and |height| specify the " + "initial screen resolution.") ] + HRESULT Connect([in] long width, [in] long height, + [in] IRdpDesktopSessionEventHandler* event_handler); + + [ id(2), helpstring("Shuts down the connection created by Connect().") ] + HRESULT Disconnect(); + + [ id(3), helpstring("Changes the screen resolution.") ] + HRESULT ChangeResolution([in] long width, [in] long height); +}; + +[ uuid(b6396c45-b0cc-456b-9f49-f12964ee6df4), version(1.0), helpstring("Chromoting 1.0 Type Library") @@ -79,4 +124,12 @@ library ChromotingLib { coclass ElevatedController { [default] interface IDaemonControl2; }; + + [ + uuid(@RDP_DESKTOP_SESSION_CLSID@), + helpstring("RdpDesktopSession Class") + ] + coclass RdpDesktopSession { + [default] interface IRdpDesktopSession; + }; }; diff --git a/remoting/host/win/chromoting_module.cc b/remoting/host/win/chromoting_module.cc index a9f62b1..6be0a50 100644 --- a/remoting/host/win/chromoting_module.cc +++ b/remoting/host/win/chromoting_module.cc @@ -8,9 +8,13 @@ #include "base/logging.h" #include "base/message_loop.h" #include "base/run_loop.h" +#include "base/win/scoped_handle.h" +#include "base/win/windows_version.h" #include "remoting/base/auto_thread_task_runner.h" +#include "remoting/base/typed_buffer.h" #include "remoting/host/host_exit_codes.h" #include "remoting/host/win/elevated_controller.h" +#include "remoting/host/win/rdp_desktop_session.h" namespace remoting { @@ -20,6 +24,55 @@ namespace { base::LazyInstance<scoped_refptr<AutoThreadTaskRunner> > g_module_task_runner = LAZY_INSTANCE_INITIALIZER; +// Lowers the process integrity level such that it does not exceed |max_level|. +// |max_level| is expected to be one of SECURITY_MANDATORY_XXX constants. +bool LowerProcessIntegrityLevel(DWORD max_level) { + base::win::ScopedHandle token; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_WRITE, + token.Receive())) { + PLOG(ERROR) << "OpenProcessToken() failed"; + return false; + } + + TypedBuffer<TOKEN_MANDATORY_LABEL> mandatory_label; + DWORD length = 0; + + // Get the size of the buffer needed to hold the mandatory label. + BOOL result = GetTokenInformation(token, TokenIntegrityLevel, + mandatory_label.get(), length, &length); + if (!result && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + // Allocate a buffer that is large enough. + TypedBuffer<TOKEN_MANDATORY_LABEL> buffer(length); + mandatory_label.Swap(buffer); + + // Get the the mandatory label. + result = GetTokenInformation(token, TokenIntegrityLevel, + mandatory_label.get(), length, &length); + } + if (!result) { + PLOG(ERROR) << "Failed to get the mandatory label"; + return false; + } + + // Read the current integrity level. + DWORD sub_authority_count = + *GetSidSubAuthorityCount(mandatory_label->Label.Sid); + DWORD* current_level = GetSidSubAuthority(mandatory_label->Label.Sid, + sub_authority_count - 1); + + // Set the integrity level to |max_level| if needed. + if (*current_level > max_level) { + *current_level = max_level; + if (!SetTokenInformation(token, TokenIntegrityLevel, mandatory_label.get(), + length)) { + PLOG(ERROR) << "Failed to set the mandatory label"; + return false; + } + } + + return true; +} + } // namespace ChromotingModule::ChromotingModule( @@ -137,4 +190,21 @@ int ElevatedControllerMain() { return module.Run() ? kSuccessExitCode : kInitializationFailed; } +// RdpClient entry point. +int RdpDesktopSessionMain() { + // Lower the integrity level to medium, which is the lowest level at which + // the RDP ActiveX control can run. + if (base::win::GetVersion() >= base::win::VERSION_VISTA) { + if (!LowerProcessIntegrityLevel(SECURITY_MANDATORY_MEDIUM_RID)) + return kInitializationFailed; + } + + ATL::_ATL_OBJMAP_ENTRY rdp_client_entry[] = { + OBJECT_ENTRY(__uuidof(RdpDesktopSession), RdpDesktopSession) + }; + + ChromotingModule module(rdp_client_entry, rdp_client_entry + 1); + return module.Run() ? kSuccessExitCode : kInitializationFailed; +} + } // namespace remoting diff --git a/remoting/host/win/chromoting_module.h b/remoting/host/win/chromoting_module.h index 4a1bd2be..2c7f1aa 100644 --- a/remoting/host/win/chromoting_module.h +++ b/remoting/host/win/chromoting_module.h @@ -13,7 +13,7 @@ #include "base/memory/ref_counted.h" #include "base/win/scoped_com_initializer.h" -// MIDL-generated declarations. +// chromoting_lib.h contains MIDL-generated declarations. #include "remoting/host/chromoting_lib.h" namespace base { diff --git a/remoting/host/win/elevated_controller.h b/remoting/host/win/elevated_controller.h index 3901bc1..23e5e31 100644 --- a/remoting/host/win/elevated_controller.h +++ b/remoting/host/win/elevated_controller.h @@ -11,21 +11,21 @@ #include "remoting/base/scoped_sc_handle_win.h" -// MIDL-generated declarations. +// chromoting_lib.h contains MIDL-generated declarations. #include "remoting/host/chromoting_lib.h" namespace remoting { -class ATL_NO_VTABLE __declspec(uuid(DAEMON_CONTROLLER_CLSID)) ElevatedController +class __declspec(uuid(DAEMON_CONTROLLER_CLSID)) ElevatedController : public ATL::CComObjectRootEx<ATL::CComSingleThreadModel>, public ATL::CComCoClass<ElevatedController, &__uuidof(ElevatedController)>, public ATL::IDispatchImpl<IDaemonControl2, &IID_IDaemonControl2, &LIBID_ChromotingLib, 1, 0> { public: - // Declare the class factory that does not lock the ATL module. This is the - // same DECLARE_CLASSFACTORY() with the exception that ATL::CComObjectNoLock - // is used unconditionally. + // Declare a class factory which must not lock the ATL module. This is the + // same as DECLARE_CLASSFACTORY() with the exception that + // ATL::CComObjectNoLock is used unconditionally. // // By default ATL generates locking class factories (by wrapping them in // ATL::CComObjectCached) for classes hosted in a DLL. This class is compiled diff --git a/remoting/host/win/rdp_client.cc b/remoting/host/win/rdp_client.cc index 2f1a134..9c1fb37 100644 --- a/remoting/host/win/rdp_client.cc +++ b/remoting/host/win/rdp_client.cc @@ -22,10 +22,6 @@ namespace remoting { namespace { -// Default width and hight of the RDP client window. -const long kDefaultWidth = 1024; -const long kDefaultHeight = 768; - // The range of addresses RdpClient may use to distinguish client connections: // 127.0.0.2 - 127.255.255.254. 127.0.0.1 is explicitly blocked by the RDP // ActiveX control. @@ -49,7 +45,7 @@ class RdpClient::Core RdpClient::EventHandler* event_handler); // Initiates a loopback RDP connection. - void Connect(); + void Connect(const SkISize& screen_size); // Initiates a graceful shutdown of the RDP connection. void Disconnect(); @@ -113,11 +109,12 @@ class RdpClient::Core RdpClient::RdpClient( scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, + const SkISize& screen_size, EventHandler* event_handler) { DCHECK(caller_task_runner->BelongsToCurrentThread()); core_ = new Core(caller_task_runner, ui_task_runner, event_handler); - core_->Connect(); + core_->Connect(screen_size); } RdpClient::~RdpClient() { @@ -136,9 +133,10 @@ RdpClient::Core::Core( get_extended_tcp_table_(NULL) { } -void RdpClient::Core::Connect() { +void RdpClient::Core::Connect(const SkISize& screen_size) { if (!ui_task_runner_->BelongsToCurrentThread()) { - ui_task_runner_->PostTask(FROM_HERE, base::Bind(&Core::Connect, this)); + ui_task_runner_->PostTask(FROM_HERE, + base::Bind(&Core::Connect, this, screen_size)); return; } @@ -170,8 +168,7 @@ void RdpClient::Core::Connect() { // Create the ActiveX control window. rdp_client_window_.reset(new RdpClientWindow(server_endpoint_, this)); - if (!rdp_client_window_->Connect(SkISize::Make(kDefaultWidth, - kDefaultHeight))) { + if (!rdp_client_window_->Connect(screen_size)) { rdp_client_window_.reset(); // Notify the caller that connection attempt failed. diff --git a/remoting/host/win/rdp_client.h b/remoting/host/win/rdp_client.h index 4987397..07a0238 100644 --- a/remoting/host/win/rdp_client.h +++ b/remoting/host/win/rdp_client.h @@ -9,6 +9,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/threading/non_thread_safe.h" +#include "third_party/skia/include/core/SkSize.h" namespace base { class SingleThreadTaskRunner; @@ -38,6 +39,7 @@ class RdpClient : public base::NonThreadSafe { RdpClient( scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, + const SkISize& screen_size, EventHandler* event_handler); virtual ~RdpClient(); diff --git a/remoting/host/win/rdp_client_unittest.cc b/remoting/host/win/rdp_client_unittest.cc index 38f59cd..f906829 100644 --- a/remoting/host/win/rdp_client_unittest.cc +++ b/remoting/host/win/rdp_client_unittest.cc @@ -25,6 +25,10 @@ namespace remoting { namespace { +// Default width and hight of the RDP client window. +const long kDefaultWidth = 1024; +const long kDefaultHeight = 768; + class MockRdpClientEventHandler : public RdpClient::EventHandler { public: MockRdpClientEventHandler() {} @@ -134,7 +138,8 @@ TEST_F(RdpClientTest, Basic) { .WillOnce(InvokeWithoutArgs(this, &RdpClientTest::CloseRdpClient)); rdp_client_.reset(new RdpClient(task_runner_, task_runner_, - &event_handler_)); + SkISize::Make(kDefaultWidth, kDefaultHeight), + &event_handler_)); task_runner_ = NULL; run_loop_.Run(); diff --git a/remoting/host/win/rdp_desktop_session.cc b/remoting/host/win/rdp_desktop_session.cc new file mode 100644 index 0000000..c555874 --- /dev/null +++ b/remoting/host/win/rdp_desktop_session.cc @@ -0,0 +1,56 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "remoting/host/win/rdp_desktop_session.h" + +#include <winsock2.h> + +#include "net/base/ip_endpoint.h" +#include "net/base/net_util.h" +#include "remoting/base/auto_thread_task_runner.h" +#include "remoting/host/win/chromoting_module.h" + +namespace remoting { + +RdpDesktopSession::RdpDesktopSession() { +} + +STDMETHODIMP RdpDesktopSession::Connect( + long width, + long height, + IRdpDesktopSessionEventHandler* event_handler) { + event_handler_ = event_handler; + + scoped_refptr<AutoThreadTaskRunner> task_runner = + ChromotingModule::task_runner(); + DCHECK(task_runner->BelongsToCurrentThread()); + + client_.reset(new RdpClient(task_runner, task_runner, + SkISize::Make(width, height), this)); + return S_OK; +} + +STDMETHODIMP RdpDesktopSession::Disconnect() { + client_.reset(); + event_handler_ = NULL; + return S_OK; +} + +STDMETHODIMP RdpDesktopSession::ChangeResolution(long width, long height) { + return E_NOTIMPL; +} + +void RdpDesktopSession::OnRdpConnected(const net::IPEndPoint& client_endpoint) { + net::SockaddrStorage sockaddr; + CHECK(client_endpoint.ToSockAddr(sockaddr.addr, &sockaddr.addr_len)); + + event_handler_->OnRdpConnected(reinterpret_cast<byte*>(sockaddr.addr), + sockaddr.addr_len); +} + +void RdpDesktopSession::OnRdpClosed() { + event_handler_->OnRdpClosed(); +} + +} // namespace remoting diff --git a/remoting/host/win/rdp_desktop_session.h b/remoting/host/win/rdp_desktop_session.h new file mode 100644 index 0000000..6ab2087 --- /dev/null +++ b/remoting/host/win/rdp_desktop_session.h @@ -0,0 +1,76 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef REMOTING_HOST_WIN_RDP_DESKTOP_SESSION_H_ +#define REMOTING_HOST_WIN_RDP_DESKTOP_SESSION_H_ + +#include <atlbase.h> +#include <atlcom.h> +#include <atlctl.h> + +#include "base/memory/scoped_ptr.h" +#include "base/win/scoped_comptr.h" +// chromoting_lib.h contains MIDL-generated declarations. +#include "remoting/host/chromoting_lib.h" +#include "remoting/host/win/rdp_client.h" + +namespace net { +class IPEndPoint; +} // namespace net + +namespace remoting { + +// Implements IRdpDesktopSession interface providing a way to host RdpClient +// objects in a COM component. +class __declspec(uuid(RDP_DESKTOP_SESSION_CLSID)) RdpDesktopSession + : public ATL::CComObjectRootEx<ATL::CComSingleThreadModel>, + public ATL::CComCoClass<RdpDesktopSession, &__uuidof(RdpDesktopSession)>, + public ATL::IDispatchImpl<IRdpDesktopSession, &IID_IRdpDesktopSession, + &LIBID_ChromotingLib, 1, 0>, + public RdpClient::EventHandler { + public: + // Declare a class factory which must not lock the ATL module. This is the + // same as DECLARE_CLASSFACTORY() with the exception that + // ATL::CComObjectNoLock is used unconditionally. + // + // By default ATL generates locking class factories (by wrapping them in + // ATL::CComObjectCached) for classes hosted in a DLL. This class is compiled + // into a DLL but it is registered as an out-of-process class, so its class + // factory should not use locking. + typedef ATL::CComCreator<ATL::CComObjectNoLock<ATL::CComClassFactory> > + _ClassFactoryCreatorClass; + + RdpDesktopSession(); + + // IRdpDesktopSession implementation. + STDMETHOD(Connect)(long width, long height, + IRdpDesktopSessionEventHandler* event_handler); + STDMETHOD(Disconnect)(); + STDMETHOD(ChangeResolution)(long width, long height); + + DECLARE_NO_REGISTRY() + + private: + // RdpClient::EventHandler interface. + virtual void OnRdpConnected(const net::IPEndPoint& client_endpoint) OVERRIDE; + virtual void OnRdpClosed() OVERRIDE; + + BEGIN_COM_MAP(RdpDesktopSession) + COM_INTERFACE_ENTRY(IRdpDesktopSession) + COM_INTERFACE_ENTRY(IDispatch) + END_COM_MAP() + + // Implements loading and instantiation of the RDP ActiveX client. + scoped_ptr<RdpClient> client_; + + // Holds a reference to the caller's EventHandler, through which notifications + // are dispatched. Released in Disconnect(), to prevent further notifications. + base::win::ScopedComPtr<IRdpDesktopSessionEventHandler> event_handler_; + + DECLARE_PROTECT_FINAL_CONSTRUCT() +}; + +} // namespace remoting + +#endif // REMOTING_HOST_WIN_RDP_DESKTOP_SESSION_H_ diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp index 7a73e44..0c2472d 100644 --- a/remoting/remoting.gyp +++ b/remoting/remoting.gyp @@ -89,10 +89,15 @@ 'host_plugin_prefix': '', }], ['OS=="win"', { - # Use auto-generated CLSID to make sure that the newly installed COM + # Use auto-generated CLSIDs to make sure that the newly installed COM # classes will be used during/after upgrade even if there are old # instances running already. - 'daemon_controller_clsid': '<!(python tools/uuidgen.py)', + # The parameter passed to uuidgen.py is ignored, but needed to make sure + # that the script will be invoked separately for each CLSID. Otherwise + # GYP will reuse the value returned by the first invocation of + # the script. + 'daemon_controller_clsid': '<!(python tools/uuidgen.py 1)', + 'rdp_desktop_session_clsid': '<!(python tools/uuidgen.py 2)', }], ], 'remoting_webapp_locale_files': [ @@ -1157,6 +1162,7 @@ 'python', '<(version_py_path)', '-e', "DAEMON_CONTROLLER_CLSID='<(daemon_controller_clsid)'", + '-e', "RDP_DESKTOP_SESSION_CLSID='<(rdp_desktop_session_clsid)'", '<(RULE_INPUT_PATH)', '<@(_outputs)', ], @@ -1304,6 +1310,7 @@ '_ATL_NO_AUTOMATIC_NAMESPACE', '_ATL_NO_EXCEPTIONS', 'DAEMON_CONTROLLER_CLSID="{<(daemon_controller_clsid)}"', + 'RDP_DESKTOP_SESSION_CLSID="{<(rdp_desktop_session_clsid)}"', 'HOST_IMPLEMENTATION', 'ISOLATION_AWARE_ENABLED=1', 'STRICT', @@ -1371,6 +1378,8 @@ 'host/win/host_service.h', 'host/win/omaha.cc', 'host/win/omaha.h', + 'host/win/rdp_desktop_session.cc', + 'host/win/rdp_desktop_session.h', 'host/win/unprivileged_process_delegate.cc', 'host/win/unprivileged_process_delegate.h', 'host/win/worker_process_launcher.cc', @@ -1723,6 +1732,7 @@ 'defs': [ 'BRANDING=<(branding)', 'DAEMON_CONTROLLER_CLSID={<(daemon_controller_clsid)}', + 'RDP_DESKTOP_SESSION_CLSID={<(rdp_desktop_session_clsid)}', 'REMOTING_MULTI_PROCESS=<(remoting_multi_process)', 'VERSION=<(version_full)', ], |