From f0ca84771013a4a7e5f391922870755b8a22e0a7 Mon Sep 17 00:00:00 2001 From: Zac Bergquist Date: Thu, 2 Nov 2023 14:19:42 -0600 Subject: [PATCH] Add support for the TS_SYNC_EVENT (#34) This is used to synchronize the state of the toggle keys (like caps lock), as well as to reset the server state to "all keys up." --- src/core/client.rs | 3 +++ src/core/event.rs | 8 ++++++++ src/core/global.rs | 30 +++++++++++++++++++++++++++++- 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/core/client.rs b/src/core/client.rs index 049864c..01994ae 100644 --- a/src/core/client.rs +++ b/src/core/client.rs @@ -102,6 +102,9 @@ impl RdpClient { } // Raw keyboard input RdpEvent::Key(key) => self.global.write_input_event(key.into(), &mut self.mcs), + // Input sync + RdpEvent::Sync(sync) => self.global.write_input_event(sync.into(), &mut self.mcs), + _ => Err(Error::RdpError(RdpError::new( RdpErrorKind::UnexpectedType, "RDPCLIENT: This event can't be sent", diff --git a/src/core/event.rs b/src/core/event.rs index 3ef1037..233918a 100644 --- a/src/core/event.rs +++ b/src/core/event.rs @@ -169,6 +169,12 @@ pub struct KeyboardEvent { pub down: bool, } +#[derive(Debug)] +pub struct InputSyncEvent { + /// Indicates which of the toggle keys are active. + pub flags: u32, +} + /// All event handle by RDP protocol implemented by rdp-rs #[derive(Debug)] pub enum RdpEvent { @@ -178,4 +184,6 @@ pub enum RdpEvent { Pointer(PointerEvent), /// Keyboard event Key(KeyboardEvent), + /// Input sync event + Sync(InputSyncEvent), } diff --git a/src/core/global.rs b/src/core/global.rs index fe188ae..e34daa9 100644 --- a/src/core/global.rs +++ b/src/core/global.rs @@ -1,7 +1,7 @@ use crate::core::capability; use crate::core::capability::{capability_set, Capability}; use crate::core::event::{ - BitmapEvent, KeyboardEvent, PointerButton, PointerEvent, PointerWheel, RdpEvent, + BitmapEvent, InputSyncEvent, KeyboardEvent, PointerButton, PointerEvent, PointerWheel, RdpEvent, }; use crate::core::gcc::KeyboardLayout; use crate::core::mcs; @@ -601,6 +601,34 @@ pub fn ts_keyboard_event(flags: Option, key_code: Option) -> TSInputEv } } +#[repr(u32)] +pub enum InputSyncFlags { + TsSyncScrollLock = 0x00000001, + TsSyncNumLock = 0x00000002, + TsSyncCapsLock = 0x00000004, + TsSyncKanaLock = 0x00000008, +} + +/// The TS_SYNC_EVENT is used to synchronize the value of the toggle keys +/// and to reset the server state to "all keys up." +/// +/// See https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/6c5d0ef9-4653-4d69-9ba9-09ba3acd660f +pub fn ts_sync_event(toggle_flags: Option) -> TSInputEvent { + TSInputEvent { + event_type: InputEventType::InputEventSync, + message: component![ + "pad2Octets" => U16::LE(0), + "toggleFlags" => U32::LE(toggle_flags.unwrap_or(0)) + ], + } +} + +impl From for TSInputEvent { + fn from(evt: InputSyncEvent) -> Self { + ts_sync_event(Some(evt.flags)) + } +} + /// Fast Path update (Not a PDU) /// /// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/a1c4caa8-00ed-45bb-a06e-5177473766d3