From d1452003b0da2646f0a6d6c00a9f1f0969c814cb Mon Sep 17 00:00:00 2001 From: irving ou Date: Fri, 5 Apr 2024 13:51:25 -0400 Subject: [PATCH 01/18] WIP:expose connected connection result --- ffi/src/connector/mod.rs | 12 +++ ffi/src/connector/result.rs | 6 +- ffi/src/connector/state.rs | 210 ++++++++++++++++++++++++++++++++++++ ffi/src/lib.rs | 1 + ffi/src/pdu.rs | 6 ++ ffi/src/session/mod.rs | 7 ++ 6 files changed, 239 insertions(+), 3 deletions(-) create mode 100644 ffi/src/session/mod.rs diff --git a/ffi/src/connector/mod.rs b/ffi/src/connector/mod.rs index 18b869487..492dfa3fe 100644 --- a/ffi/src/connector/mod.rs +++ b/ffi/src/connector/mod.rs @@ -161,4 +161,16 @@ pub mod ffi { Ok(Box::new(State(connector.state()))) } } + + + + + #[diplomat::opaque] + pub struct ChannelConnectionSequence(pub ironrdp::connector::ChannelConnectionSequence); + + #[diplomat::opaque] + pub struct LicenseExchangeSequence(pub ironrdp::connector::LicenseExchangeSequence); + + #[diplomat::opaque] + pub struct ConnectionActivationSequence(pub ironrdp::connector::connection_activation::ConnectionActivationSequence); } diff --git a/ffi/src/connector/result.rs b/ffi/src/connector/result.rs index cffea1a7b..ba86ba276 100644 --- a/ffi/src/connector/result.rs +++ b/ffi/src/connector/result.rs @@ -27,9 +27,9 @@ pub mod ffi { } #[diplomat::opaque] - pub struct ConnectionResult(pub ironrdp::connector::ConnectionResult); + pub struct ConnectionResult<'a>(pub &'a ironrdp::connector::ConnectionResult); - impl ConnectionResult { + impl<'a> ConnectionResult<'a> { pub fn get_io_channel_id(&self) -> u16 { self.0.io_channel_id } @@ -38,7 +38,7 @@ pub mod ffi { self.0.user_channel_id } - pub fn get_static_channels(&self) -> Box> { + pub fn get_static_channels(&'a self) -> Box> { Box::new(crate::svc::ffi::StaticChannelSet(&self.0.static_channels)) } diff --git a/ffi/src/connector/state.rs b/ffi/src/connector/state.rs index de892368c..6f00f5258 100644 --- a/ffi/src/connector/state.rs +++ b/ffi/src/connector/state.rs @@ -1,6 +1,216 @@ #[diplomat::bridge] pub mod ffi { + use crate::pdu::ffi::SecurityProtocol; #[diplomat::opaque] pub struct ClientConnectorState(pub ironrdp::connector::ClientConnectorState); + + pub enum ClientConnectorStateType { + Consumed, + ConnectionInitiationSendRequest, + ConnectionInitiationWaitConfirm, + EnhancedSecurityUpgrade, + Credssp, + BasicSettingsExchangeSendInitial, + BasicSettingsExchangeWaitResponse, + ChannelConnection, + SecureSettingsExchange, + ConnectTimeAutoDetection, + LicensingExchange, + MultitransportBootstrapping, + CapabilitiesExchange, + ConnectionFinalization, + Connected, + } + + impl ClientConnectorState { + pub fn get_type(&self) -> Result> { + let res = match &self.0 { + ironrdp::connector::ClientConnectorState::Consumed => ClientConnectorStateType::Consumed, + ironrdp::connector::ClientConnectorState::ConnectionInitiationSendRequest => { + ClientConnectorStateType::ConnectionInitiationSendRequest + } + ironrdp::connector::ClientConnectorState::ConnectionInitiationWaitConfirm { .. } => { + ClientConnectorStateType::ConnectionInitiationWaitConfirm + } + ironrdp::connector::ClientConnectorState::EnhancedSecurityUpgrade { .. } => { + ClientConnectorStateType::EnhancedSecurityUpgrade + } + ironrdp::connector::ClientConnectorState::Credssp { .. } => ClientConnectorStateType::Credssp, + ironrdp::connector::ClientConnectorState::BasicSettingsExchangeSendInitial { .. } => { + ClientConnectorStateType::BasicSettingsExchangeSendInitial + } + ironrdp::connector::ClientConnectorState::BasicSettingsExchangeWaitResponse { .. } => { + ClientConnectorStateType::BasicSettingsExchangeWaitResponse + } + ironrdp::connector::ClientConnectorState::ChannelConnection { .. } => { + ClientConnectorStateType::ChannelConnection + } + ironrdp::connector::ClientConnectorState::SecureSettingsExchange { .. } => { + ClientConnectorStateType::SecureSettingsExchange + } + ironrdp::connector::ClientConnectorState::ConnectTimeAutoDetection { .. } => { + ClientConnectorStateType::ConnectTimeAutoDetection + } + ironrdp::connector::ClientConnectorState::LicensingExchange { .. } => { + ClientConnectorStateType::LicensingExchange + } + ironrdp::connector::ClientConnectorState::MultitransportBootstrapping { .. } => { + ClientConnectorStateType::MultitransportBootstrapping + } + ironrdp::connector::ClientConnectorState::CapabilitiesExchange { .. } => { + ClientConnectorStateType::CapabilitiesExchange + } + ironrdp::connector::ClientConnectorState::ConnectionFinalization { .. } => { + ClientConnectorStateType::ConnectionFinalization + } + ironrdp::connector::ClientConnectorState::Connected { .. } => ClientConnectorStateType::Connected, + &_ => return Err("Unknown ClientConnectorStateType".into()), + }; + + Ok(res) + } + + pub fn get_connection_initiation_wait_confirm_requested_protocol( + &self, + ) -> Result, Box> { + match &self.0 { + ironrdp::connector::ClientConnectorState::ConnectionInitiationWaitConfirm { requested_protocol } => { + Ok(SecurityProtocol(*requested_protocol)) + } + _ => Err("Not in ConnectionInitiationWaitConfirm state".into()), + } + .map(Box::new) + } + + pub fn get_enhanced_security_upgrade_selected_protocol( + &self, + ) -> Result, Box> { + match &self.0 { + ironrdp::connector::ClientConnectorState::EnhancedSecurityUpgrade { selected_protocol } => { + Ok(SecurityProtocol(*selected_protocol)) + } + _ => Err("Not in EnhancedSecurityUpgrade state".into()), + } + .map(Box::new) + } + + pub fn get_credssp_selected_protocol( + &self, + ) -> Result, Box> { + match &self.0 { + ironrdp::connector::ClientConnectorState::Credssp { selected_protocol } => { + Ok(SecurityProtocol(*selected_protocol)) + } + _ => Err("Not in Credssp state".into()), + } + .map(Box::new) + } + + pub fn get_basic_settings_exchange_send_initial_selected_protocol( + &self, + ) -> Result, Box> { + match &self.0 { + ironrdp::connector::ClientConnectorState::BasicSettingsExchangeSendInitial { selected_protocol } => { + Ok(SecurityProtocol(*selected_protocol)) + } + _ => Err("Not in BasicSettingsExchangeSendInitial state".into()), + } + .map(Box::new) + } + + pub fn get_basic_settings_exchange_wait_response_connect_initial( + &self, + ) -> Result, Box> { + match &self.0 { + ironrdp::connector::ClientConnectorState::BasicSettingsExchangeWaitResponse { connect_initial } => { + Ok(crate::pdu::ffi::ConnectInitial(connect_initial.clone())) + } + _ => Err("Not in BasicSettingsExchangeWaitResponse state".into()), + } + .map(Box::new) + } + + pub fn get_channel_connection_io_channel_id(&self) -> Result> { + match &self.0 { + ironrdp::connector::ClientConnectorState::ChannelConnection { io_channel_id, .. } => Ok(*io_channel_id), + _ => Err("Not in ChannelConnection state".into()), + } + } + + pub fn get_secure_settings_exchange_io_channel_id(&self) -> Result> { + match &self.0 { + ironrdp::connector::ClientConnectorState::SecureSettingsExchange { io_channel_id, .. } => { + Ok(*io_channel_id) + } + _ => Err("Not in SecureSettingsExchange state".into()), + } + } + + // TODO: Add more getters for other states + + pub fn get_connected_result( + &self, + ) -> Result, Box> + { + match &self.0 { + ironrdp::connector::ClientConnectorState::Connected { result } => Ok(Box::new( + crate::connector::result::ffi::ConnectionResult(result.clone()), + )), + _ => Err("Not in Connected state".into()), + } + } + } + + // pub enum ClientConnectorState { + // #[default] + // Consumed, + + // ConnectionInitiationSendRequest, + // ConnectionInitiationWaitConfirm { + // requested_protocol: nego::SecurityProtocol, + // }, + // EnhancedSecurityUpgrade { + // selected_protocol: nego::SecurityProtocol, + // }, + // Credssp { + // selected_protocol: nego::SecurityProtocol, + // }, + // BasicSettingsExchangeSendInitial { + // selected_protocol: nego::SecurityProtocol, + // }, + // BasicSettingsExchangeWaitResponse { + // connect_initial: mcs::ConnectInitial, + // }, + // ChannelConnection { + // io_channel_id: u16, + // channel_connection: ChannelConnectionSequence, + // }, + // SecureSettingsExchange { + // io_channel_id: u16, + // user_channel_id: u16, + // }, + // ConnectTimeAutoDetection { + // io_channel_id: u16, + // user_channel_id: u16, + // }, + // LicensingExchange { + // io_channel_id: u16, + // user_channel_id: u16, + // license_exchange: LicenseExchangeSequence, + // }, + // MultitransportBootstrapping { + // io_channel_id: u16, + // user_channel_id: u16, + // }, + // CapabilitiesExchange { + // connection_activation: ConnectionActivationSequence, + // }, + // ConnectionFinalization { + // connection_activation: ConnectionActivationSequence, + // }, + // Connected { + // result: ConnectionResult, + // }, + // } } diff --git a/ffi/src/lib.rs b/ffi/src/lib.rs index d8884366b..ff2e013c9 100644 --- a/ffi/src/lib.rs +++ b/ffi/src/lib.rs @@ -7,3 +7,4 @@ pub mod error; pub mod pdu; pub mod svc; pub mod utils; +pub mod session; diff --git a/ffi/src/pdu.rs b/ffi/src/pdu.rs index a7f887e6f..5302986d1 100644 --- a/ffi/src/pdu.rs +++ b/ffi/src/pdu.rs @@ -20,4 +20,10 @@ pub mod ffi { Ok(()) } } + + #[diplomat::opaque] + pub struct SecurityProtocol(pub ironrdp::pdu::nego::SecurityProtocol); + + #[diplomat::opaque] + pub struct ConnectInitial(pub ironrdp::pdu::mcs::ConnectInitial); } diff --git a/ffi/src/session/mod.rs b/ffi/src/session/mod.rs new file mode 100644 index 000000000..96299bbba --- /dev/null +++ b/ffi/src/session/mod.rs @@ -0,0 +1,7 @@ + +#[diplomat::bridge] +pub mod ffi { + + #[diplomat::opaque] + pub struct ActiveStage(pub ironrdp::session::ActiveStage); +} \ No newline at end of file From cd101b2be545c597e71e9ae10299521e56804102 Mon Sep 17 00:00:00 2001 From: irving ou Date: Fri, 5 Apr 2024 14:03:32 -0400 Subject: [PATCH 02/18] WIP:diplomat works for connection result --- .../Generated/ClientConnectorState.cs | 264 ++++++++++++++++++ .../Generated/ConfigBuilder.cs | 4 +- .../Generated/RawClientConnectorState.cs | 27 ++ .../Generated/RawConfigBuilder.cs | 4 +- ffi/src/connector/mod.rs | 3 - ffi/src/connector/state.rs | 77 +---- 6 files changed, 308 insertions(+), 71 deletions(-) diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/ClientConnectorState.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/ClientConnectorState.cs index 127bc83cb..dbe82b0c2 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/ClientConnectorState.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/ClientConnectorState.cs @@ -15,6 +15,78 @@ public partial class ClientConnectorState: IDisposable { private unsafe Raw.ClientConnectorState* _inner; + public SecurityProtocol BasicSettingsExchangeSendInitialSelectedProtocol + { + get + { + return GetBasicSettingsExchangeSendInitialSelectedProtocol(); + } + } + + public ConnectInitial BasicSettingsExchangeWaitResponseConnectInitial + { + get + { + return GetBasicSettingsExchangeWaitResponseConnectInitial(); + } + } + + public ushort ChannelConnectionIoChannelId + { + get + { + return GetChannelConnectionIoChannelId(); + } + } + + public ConnectionResult ConnectedResult + { + get + { + return GetConnectedResult(); + } + } + + public SecurityProtocol ConnectionInitiationWaitConfirmRequestedProtocol + { + get + { + return GetConnectionInitiationWaitConfirmRequestedProtocol(); + } + } + + public SecurityProtocol CredsspSelectedProtocol + { + get + { + return GetCredsspSelectedProtocol(); + } + } + + public SecurityProtocol EnhancedSecurityUpgradeSelectedProtocol + { + get + { + return GetEnhancedSecurityUpgradeSelectedProtocol(); + } + } + + public ushort SecureSettingsExchangeIoChannelId + { + get + { + return GetSecureSettingsExchangeIoChannelId(); + } + } + + public ClientConnectorStateType Type + { + get + { + return GetType(); + } + } + /// /// Creates a managed ClientConnectorState from a raw handle. /// @@ -29,6 +101,198 @@ public unsafe ClientConnectorState(Raw.ClientConnectorState* handle) _inner = handle; } + /// + /// + /// A ClientConnectorStateType allocated on C# side. + /// + public ClientConnectorStateType GetType() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ClientConnectorState"); + } + Raw.ConnectorStateFfiResultClientConnectorStateTypeBoxIronRdpError result = Raw.ClientConnectorState.GetType(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.ClientConnectorStateType retVal = result.Ok; + return (ClientConnectorStateType)retVal; + } + } + + /// + /// + /// A SecurityProtocol allocated on Rust side. + /// + public SecurityProtocol GetConnectionInitiationWaitConfirmRequestedProtocol() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ClientConnectorState"); + } + Raw.ConnectorStateFfiResultBoxSecurityProtocolBoxIronRdpError result = Raw.ClientConnectorState.GetConnectionInitiationWaitConfirmRequestedProtocol(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.SecurityProtocol* retVal = result.Ok; + return new SecurityProtocol(retVal); + } + } + + /// + /// + /// A SecurityProtocol allocated on Rust side. + /// + public SecurityProtocol GetEnhancedSecurityUpgradeSelectedProtocol() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ClientConnectorState"); + } + Raw.ConnectorStateFfiResultBoxSecurityProtocolBoxIronRdpError result = Raw.ClientConnectorState.GetEnhancedSecurityUpgradeSelectedProtocol(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.SecurityProtocol* retVal = result.Ok; + return new SecurityProtocol(retVal); + } + } + + /// + /// + /// A SecurityProtocol allocated on Rust side. + /// + public SecurityProtocol GetCredsspSelectedProtocol() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ClientConnectorState"); + } + Raw.ConnectorStateFfiResultBoxSecurityProtocolBoxIronRdpError result = Raw.ClientConnectorState.GetCredsspSelectedProtocol(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.SecurityProtocol* retVal = result.Ok; + return new SecurityProtocol(retVal); + } + } + + /// + /// + /// A SecurityProtocol allocated on Rust side. + /// + public SecurityProtocol GetBasicSettingsExchangeSendInitialSelectedProtocol() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ClientConnectorState"); + } + Raw.ConnectorStateFfiResultBoxSecurityProtocolBoxIronRdpError result = Raw.ClientConnectorState.GetBasicSettingsExchangeSendInitialSelectedProtocol(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.SecurityProtocol* retVal = result.Ok; + return new SecurityProtocol(retVal); + } + } + + /// + /// + /// A ConnectInitial allocated on Rust side. + /// + public ConnectInitial GetBasicSettingsExchangeWaitResponseConnectInitial() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ClientConnectorState"); + } + Raw.ConnectorStateFfiResultBoxConnectInitialBoxIronRdpError result = Raw.ClientConnectorState.GetBasicSettingsExchangeWaitResponseConnectInitial(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.ConnectInitial* retVal = result.Ok; + return new ConnectInitial(retVal); + } + } + + /// + public ushort GetChannelConnectionIoChannelId() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ClientConnectorState"); + } + Raw.ConnectorStateFfiResultU16BoxIronRdpError result = Raw.ClientConnectorState.GetChannelConnectionIoChannelId(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + ushort retVal = result.Ok; + return retVal; + } + } + + /// + public ushort GetSecureSettingsExchangeIoChannelId() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ClientConnectorState"); + } + Raw.ConnectorStateFfiResultU16BoxIronRdpError result = Raw.ClientConnectorState.GetSecureSettingsExchangeIoChannelId(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + ushort retVal = result.Ok; + return retVal; + } + } + + /// + /// + /// A ConnectionResult allocated on Rust side. + /// + public ConnectionResult GetConnectedResult() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ClientConnectorState"); + } + Raw.ConnectorStateFfiResultBoxConnectionResultBoxIronRdpError result = Raw.ClientConnectorState.GetConnectedResult(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.ConnectionResult* retVal = result.Ok; + return new ConnectionResult(retVal); + } + } + /// /// Returns the underlying raw handle. /// diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/ConfigBuilder.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/ConfigBuilder.cs index b3f46e34f..f821ebfb3 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/ConfigBuilder.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/ConfigBuilder.cs @@ -161,7 +161,7 @@ public static ConfigBuilder New() } } - public void WithUsernameAndPasswrord(string username, string password) + public void WithUsernameAndPassword(string username, string password) { unsafe { @@ -177,7 +177,7 @@ public void WithUsernameAndPasswrord(string username, string password) { fixed (byte* passwordBufPtr = passwordBuf) { - Raw.ConfigBuilder.WithUsernameAndPasswrord(_inner, usernameBufPtr, usernameBufLength, passwordBufPtr, passwordBufLength); + Raw.ConfigBuilder.WithUsernameAndPassword(_inner, usernameBufPtr, usernameBufLength, passwordBufPtr, passwordBufLength); } } } diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawClientConnectorState.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawClientConnectorState.cs index 669ae9c03..da4fd6a0d 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/RawClientConnectorState.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawClientConnectorState.cs @@ -16,6 +16,33 @@ public partial struct ClientConnectorState { private const string NativeLib = "DevolutionsIronRdp"; + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnectorState_get_type", ExactSpelling = true)] + public static unsafe extern ConnectorStateFfiResultClientConnectorStateTypeBoxIronRdpError GetType(ClientConnectorState* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnectorState_get_connection_initiation_wait_confirm_requested_protocol", ExactSpelling = true)] + public static unsafe extern ConnectorStateFfiResultBoxSecurityProtocolBoxIronRdpError GetConnectionInitiationWaitConfirmRequestedProtocol(ClientConnectorState* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnectorState_get_enhanced_security_upgrade_selected_protocol", ExactSpelling = true)] + public static unsafe extern ConnectorStateFfiResultBoxSecurityProtocolBoxIronRdpError GetEnhancedSecurityUpgradeSelectedProtocol(ClientConnectorState* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnectorState_get_credssp_selected_protocol", ExactSpelling = true)] + public static unsafe extern ConnectorStateFfiResultBoxSecurityProtocolBoxIronRdpError GetCredsspSelectedProtocol(ClientConnectorState* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnectorState_get_basic_settings_exchange_send_initial_selected_protocol", ExactSpelling = true)] + public static unsafe extern ConnectorStateFfiResultBoxSecurityProtocolBoxIronRdpError GetBasicSettingsExchangeSendInitialSelectedProtocol(ClientConnectorState* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnectorState_get_basic_settings_exchange_wait_response_connect_initial", ExactSpelling = true)] + public static unsafe extern ConnectorStateFfiResultBoxConnectInitialBoxIronRdpError GetBasicSettingsExchangeWaitResponseConnectInitial(ClientConnectorState* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnectorState_get_channel_connection_io_channel_id", ExactSpelling = true)] + public static unsafe extern ConnectorStateFfiResultU16BoxIronRdpError GetChannelConnectionIoChannelId(ClientConnectorState* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnectorState_get_secure_settings_exchange_io_channel_id", ExactSpelling = true)] + public static unsafe extern ConnectorStateFfiResultU16BoxIronRdpError GetSecureSettingsExchangeIoChannelId(ClientConnectorState* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnectorState_get_connected_result", ExactSpelling = true)] + public static unsafe extern ConnectorStateFfiResultBoxConnectionResultBoxIronRdpError GetConnectedResult(ClientConnectorState* self); + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnectorState_destroy", ExactSpelling = true)] public static unsafe extern void Destroy(ClientConnectorState* self); } diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConfigBuilder.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConfigBuilder.cs index ac96aefb7..08a19c4ef 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConfigBuilder.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConfigBuilder.cs @@ -19,8 +19,8 @@ public partial struct ConfigBuilder [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConfigBuilder_new", ExactSpelling = true)] public static unsafe extern ConfigBuilder* New(); - [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConfigBuilder_with_username_and_passwrord", ExactSpelling = true)] - public static unsafe extern void WithUsernameAndPasswrord(ConfigBuilder* self, byte* username, nuint usernameSz, byte* password, nuint passwordSz); + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConfigBuilder_with_username_and_password", ExactSpelling = true)] + public static unsafe extern void WithUsernameAndPassword(ConfigBuilder* self, byte* username, nuint usernameSz, byte* password, nuint passwordSz); [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConfigBuilder_set_domain", ExactSpelling = true)] public static unsafe extern void SetDomain(ConfigBuilder* self, byte* domain, nuint domainSz); diff --git a/ffi/src/connector/mod.rs b/ffi/src/connector/mod.rs index 492dfa3fe..f76f262f3 100644 --- a/ffi/src/connector/mod.rs +++ b/ffi/src/connector/mod.rs @@ -162,9 +162,6 @@ pub mod ffi { } } - - - #[diplomat::opaque] pub struct ChannelConnectionSequence(pub ironrdp::connector::ChannelConnectionSequence); diff --git a/ffi/src/connector/state.rs b/ffi/src/connector/state.rs index 6f00f5258..34997face 100644 --- a/ffi/src/connector/state.rs +++ b/ffi/src/connector/state.rs @@ -1,6 +1,6 @@ #[diplomat::bridge] pub mod ffi { - use crate::pdu::ffi::SecurityProtocol; + use crate::{error::ffi::IronRdpError, pdu::ffi::SecurityProtocol}; #[diplomat::opaque] pub struct ClientConnectorState(pub ironrdp::connector::ClientConnectorState); @@ -24,7 +24,7 @@ pub mod ffi { } impl ClientConnectorState { - pub fn get_type(&self) -> Result> { + pub fn get_type(&self) -> Result> { let res = match &self.0 { ironrdp::connector::ClientConnectorState::Consumed => ClientConnectorStateType::Consumed, ironrdp::connector::ClientConnectorState::ConnectionInitiationSendRequest => { @@ -73,7 +73,7 @@ pub mod ffi { pub fn get_connection_initiation_wait_confirm_requested_protocol( &self, - ) -> Result, Box> { + ) -> Result, Box> { match &self.0 { ironrdp::connector::ClientConnectorState::ConnectionInitiationWaitConfirm { requested_protocol } => { Ok(SecurityProtocol(*requested_protocol)) @@ -85,7 +85,7 @@ pub mod ffi { pub fn get_enhanced_security_upgrade_selected_protocol( &self, - ) -> Result, Box> { + ) -> Result, Box> { match &self.0 { ironrdp::connector::ClientConnectorState::EnhancedSecurityUpgrade { selected_protocol } => { Ok(SecurityProtocol(*selected_protocol)) @@ -97,7 +97,7 @@ pub mod ffi { pub fn get_credssp_selected_protocol( &self, - ) -> Result, Box> { + ) -> Result, Box> { match &self.0 { ironrdp::connector::ClientConnectorState::Credssp { selected_protocol } => { Ok(SecurityProtocol(*selected_protocol)) @@ -109,7 +109,7 @@ pub mod ffi { pub fn get_basic_settings_exchange_send_initial_selected_protocol( &self, - ) -> Result, Box> { + ) -> Result, Box> { match &self.0 { ironrdp::connector::ClientConnectorState::BasicSettingsExchangeSendInitial { selected_protocol } => { Ok(SecurityProtocol(*selected_protocol)) @@ -121,7 +121,7 @@ pub mod ffi { pub fn get_basic_settings_exchange_wait_response_connect_initial( &self, - ) -> Result, Box> { + ) -> Result, Box> { match &self.0 { ironrdp::connector::ClientConnectorState::BasicSettingsExchangeWaitResponse { connect_initial } => { Ok(crate::pdu::ffi::ConnectInitial(connect_initial.clone())) @@ -131,14 +131,14 @@ pub mod ffi { .map(Box::new) } - pub fn get_channel_connection_io_channel_id(&self) -> Result> { + pub fn get_channel_connection_io_channel_id(&self) -> Result> { match &self.0 { ironrdp::connector::ClientConnectorState::ChannelConnection { io_channel_id, .. } => Ok(*io_channel_id), _ => Err("Not in ChannelConnection state".into()), } } - pub fn get_secure_settings_exchange_io_channel_id(&self) -> Result> { + pub fn get_secure_settings_exchange_io_channel_id(&self) -> Result> { match &self.0 { ironrdp::connector::ClientConnectorState::SecureSettingsExchange { io_channel_id, .. } => { Ok(*io_channel_id) @@ -149,68 +149,17 @@ pub mod ffi { // TODO: Add more getters for other states - pub fn get_connected_result( - &self, - ) -> Result, Box> + pub fn get_connected_result<'a>( + &'a self, + ) -> Result>, Box> { match &self.0 { ironrdp::connector::ClientConnectorState::Connected { result } => Ok(Box::new( - crate::connector::result::ffi::ConnectionResult(result.clone()), + crate::connector::result::ffi::ConnectionResult(result), )), _ => Err("Not in Connected state".into()), } } } - // pub enum ClientConnectorState { - // #[default] - // Consumed, - - // ConnectionInitiationSendRequest, - // ConnectionInitiationWaitConfirm { - // requested_protocol: nego::SecurityProtocol, - // }, - // EnhancedSecurityUpgrade { - // selected_protocol: nego::SecurityProtocol, - // }, - // Credssp { - // selected_protocol: nego::SecurityProtocol, - // }, - // BasicSettingsExchangeSendInitial { - // selected_protocol: nego::SecurityProtocol, - // }, - // BasicSettingsExchangeWaitResponse { - // connect_initial: mcs::ConnectInitial, - // }, - // ChannelConnection { - // io_channel_id: u16, - // channel_connection: ChannelConnectionSequence, - // }, - // SecureSettingsExchange { - // io_channel_id: u16, - // user_channel_id: u16, - // }, - // ConnectTimeAutoDetection { - // io_channel_id: u16, - // user_channel_id: u16, - // }, - // LicensingExchange { - // io_channel_id: u16, - // user_channel_id: u16, - // license_exchange: LicenseExchangeSequence, - // }, - // MultitransportBootstrapping { - // io_channel_id: u16, - // user_channel_id: u16, - // }, - // CapabilitiesExchange { - // connection_activation: ConnectionActivationSequence, - // }, - // ConnectionFinalization { - // connection_activation: ConnectionActivationSequence, - // }, - // Connected { - // result: ConnectionResult, - // }, - // } } From 93b7a4ed7d8a5ca1e00b408d51c6b6798e69a99b Mon Sep 17 00:00:00 2001 From: irving ou Date: Fri, 5 Apr 2024 14:03:45 -0400 Subject: [PATCH 03/18] WIP:diplomat works for connection result --- .../Generated/ActiveStage.cs | 63 +++++++++++++++++++ .../Generated/ChannelConnectionSequence.cs | 63 +++++++++++++++++++ .../Generated/ClientConnectorStateType.cs | 31 +++++++++ .../Generated/ConnectInitial.cs | 63 +++++++++++++++++++ .../Generated/ConnectionActivationSequence.cs | 63 +++++++++++++++++++ .../Generated/LicenseExchangeSequence.cs | 63 +++++++++++++++++++ .../Generated/RawActiveStage.cs | 21 +++++++ .../Generated/RawChannelConnectionSequence.cs | 21 +++++++ .../Generated/RawClientConnectorStateType.cs | 31 +++++++++ .../Generated/RawConnectInitial.cs | 21 +++++++ .../RawConnectionActivationSequence.cs | 21 +++++++ ...iResultBoxConnectInitialBoxIronRdpError.cs | 46 ++++++++++++++ ...esultBoxConnectionResultBoxIronRdpError.cs | 46 ++++++++++++++ ...esultBoxSecurityProtocolBoxIronRdpError.cs | 46 ++++++++++++++ ...ClientConnectorStateTypeBoxIronRdpError.cs | 46 ++++++++++++++ ...nnectorStateFfiResultU16BoxIronRdpError.cs | 46 ++++++++++++++ .../Generated/RawLicenseExchangeSequence.cs | 21 +++++++ .../Generated/RawSecurityProtocol.cs | 21 +++++++ .../Generated/SecurityProtocol.cs | 63 +++++++++++++++++++ 19 files changed, 796 insertions(+) create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStage.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/ChannelConnectionSequence.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/ClientConnectorStateType.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/ConnectInitial.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/ConnectionActivationSequence.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/LicenseExchangeSequence.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStage.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawChannelConnectionSequence.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawClientConnectorStateType.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectInitial.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectionActivationSequence.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorStateFfiResultBoxConnectInitialBoxIronRdpError.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorStateFfiResultBoxConnectionResultBoxIronRdpError.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorStateFfiResultBoxSecurityProtocolBoxIronRdpError.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorStateFfiResultClientConnectorStateTypeBoxIronRdpError.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorStateFfiResultU16BoxIronRdpError.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawLicenseExchangeSequence.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawSecurityProtocol.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/SecurityProtocol.cs diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStage.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStage.cs new file mode 100644 index 000000000..641df3e6c --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStage.cs @@ -0,0 +1,63 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp; + +#nullable enable + +public partial class ActiveStage: IDisposable +{ + private unsafe Raw.ActiveStage* _inner; + + /// + /// Creates a managed ActiveStage from a raw handle. + /// + /// + /// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free). + ///
+ /// This constructor assumes the raw struct is allocated on Rust side. + /// If implemented, the custom Drop implementation on Rust side WILL run on destruction. + ///
+ public unsafe ActiveStage(Raw.ActiveStage* handle) + { + _inner = handle; + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.ActiveStage* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.ActiveStage.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~ActiveStage() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/ChannelConnectionSequence.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/ChannelConnectionSequence.cs new file mode 100644 index 000000000..19231a2c1 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/ChannelConnectionSequence.cs @@ -0,0 +1,63 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp; + +#nullable enable + +public partial class ChannelConnectionSequence: IDisposable +{ + private unsafe Raw.ChannelConnectionSequence* _inner; + + /// + /// Creates a managed ChannelConnectionSequence from a raw handle. + /// + /// + /// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free). + ///
+ /// This constructor assumes the raw struct is allocated on Rust side. + /// If implemented, the custom Drop implementation on Rust side WILL run on destruction. + ///
+ public unsafe ChannelConnectionSequence(Raw.ChannelConnectionSequence* handle) + { + _inner = handle; + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.ChannelConnectionSequence* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.ChannelConnectionSequence.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~ChannelConnectionSequence() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/ClientConnectorStateType.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/ClientConnectorStateType.cs new file mode 100644 index 000000000..27a5199e8 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/ClientConnectorStateType.cs @@ -0,0 +1,31 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp; + +#nullable enable + +public enum ClientConnectorStateType +{ + Consumed = 0, + ConnectionInitiationSendRequest = 1, + ConnectionInitiationWaitConfirm = 2, + EnhancedSecurityUpgrade = 3, + Credssp = 4, + BasicSettingsExchangeSendInitial = 5, + BasicSettingsExchangeWaitResponse = 6, + ChannelConnection = 7, + SecureSettingsExchange = 8, + ConnectTimeAutoDetection = 9, + LicensingExchange = 10, + MultitransportBootstrapping = 11, + CapabilitiesExchange = 12, + ConnectionFinalization = 13, + Connected = 14, +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/ConnectInitial.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/ConnectInitial.cs new file mode 100644 index 000000000..8a8f676b6 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/ConnectInitial.cs @@ -0,0 +1,63 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp; + +#nullable enable + +public partial class ConnectInitial: IDisposable +{ + private unsafe Raw.ConnectInitial* _inner; + + /// + /// Creates a managed ConnectInitial from a raw handle. + /// + /// + /// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free). + ///
+ /// This constructor assumes the raw struct is allocated on Rust side. + /// If implemented, the custom Drop implementation on Rust side WILL run on destruction. + ///
+ public unsafe ConnectInitial(Raw.ConnectInitial* handle) + { + _inner = handle; + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.ConnectInitial* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.ConnectInitial.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~ConnectInitial() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/ConnectionActivationSequence.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/ConnectionActivationSequence.cs new file mode 100644 index 000000000..5c6e57fe9 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/ConnectionActivationSequence.cs @@ -0,0 +1,63 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp; + +#nullable enable + +public partial class ConnectionActivationSequence: IDisposable +{ + private unsafe Raw.ConnectionActivationSequence* _inner; + + /// + /// Creates a managed ConnectionActivationSequence from a raw handle. + /// + /// + /// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free). + ///
+ /// This constructor assumes the raw struct is allocated on Rust side. + /// If implemented, the custom Drop implementation on Rust side WILL run on destruction. + ///
+ public unsafe ConnectionActivationSequence(Raw.ConnectionActivationSequence* handle) + { + _inner = handle; + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.ConnectionActivationSequence* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.ConnectionActivationSequence.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~ConnectionActivationSequence() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/LicenseExchangeSequence.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/LicenseExchangeSequence.cs new file mode 100644 index 000000000..b80e82607 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/LicenseExchangeSequence.cs @@ -0,0 +1,63 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp; + +#nullable enable + +public partial class LicenseExchangeSequence: IDisposable +{ + private unsafe Raw.LicenseExchangeSequence* _inner; + + /// + /// Creates a managed LicenseExchangeSequence from a raw handle. + /// + /// + /// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free). + ///
+ /// This constructor assumes the raw struct is allocated on Rust side. + /// If implemented, the custom Drop implementation on Rust side WILL run on destruction. + ///
+ public unsafe LicenseExchangeSequence(Raw.LicenseExchangeSequence* handle) + { + _inner = handle; + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.LicenseExchangeSequence* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.LicenseExchangeSequence.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~LicenseExchangeSequence() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStage.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStage.cs new file mode 100644 index 000000000..40298f76e --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStage.cs @@ -0,0 +1,21 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct ActiveStage +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStage_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(ActiveStage* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawChannelConnectionSequence.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawChannelConnectionSequence.cs new file mode 100644 index 000000000..74f3c82ca --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawChannelConnectionSequence.cs @@ -0,0 +1,21 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct ChannelConnectionSequence +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ChannelConnectionSequence_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(ChannelConnectionSequence* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawClientConnectorStateType.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawClientConnectorStateType.cs new file mode 100644 index 000000000..32b51771d --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawClientConnectorStateType.cs @@ -0,0 +1,31 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +public enum ClientConnectorStateType +{ + Consumed = 0, + ConnectionInitiationSendRequest = 1, + ConnectionInitiationWaitConfirm = 2, + EnhancedSecurityUpgrade = 3, + Credssp = 4, + BasicSettingsExchangeSendInitial = 5, + BasicSettingsExchangeWaitResponse = 6, + ChannelConnection = 7, + SecureSettingsExchange = 8, + ConnectTimeAutoDetection = 9, + LicensingExchange = 10, + MultitransportBootstrapping = 11, + CapabilitiesExchange = 12, + ConnectionFinalization = 13, + Connected = 14, +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectInitial.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectInitial.cs new file mode 100644 index 000000000..12e18464f --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectInitial.cs @@ -0,0 +1,21 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct ConnectInitial +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConnectInitial_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(ConnectInitial* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectionActivationSequence.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectionActivationSequence.cs new file mode 100644 index 000000000..846de2205 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectionActivationSequence.cs @@ -0,0 +1,21 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct ConnectionActivationSequence +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConnectionActivationSequence_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(ConnectionActivationSequence* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorStateFfiResultBoxConnectInitialBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorStateFfiResultBoxConnectInitialBoxIronRdpError.cs new file mode 100644 index 000000000..57848c690 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorStateFfiResultBoxConnectInitialBoxIronRdpError.cs @@ -0,0 +1,46 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct ConnectorStateFfiResultBoxConnectInitialBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal ConnectInitial* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe ConnectInitial* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorStateFfiResultBoxConnectionResultBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorStateFfiResultBoxConnectionResultBoxIronRdpError.cs new file mode 100644 index 000000000..e1b2b186e --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorStateFfiResultBoxConnectionResultBoxIronRdpError.cs @@ -0,0 +1,46 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct ConnectorStateFfiResultBoxConnectionResultBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal ConnectionResult* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe ConnectionResult* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorStateFfiResultBoxSecurityProtocolBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorStateFfiResultBoxSecurityProtocolBoxIronRdpError.cs new file mode 100644 index 000000000..e4e098e1a --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorStateFfiResultBoxSecurityProtocolBoxIronRdpError.cs @@ -0,0 +1,46 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct ConnectorStateFfiResultBoxSecurityProtocolBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal SecurityProtocol* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe SecurityProtocol* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorStateFfiResultClientConnectorStateTypeBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorStateFfiResultClientConnectorStateTypeBoxIronRdpError.cs new file mode 100644 index 000000000..05c250ce4 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorStateFfiResultClientConnectorStateTypeBoxIronRdpError.cs @@ -0,0 +1,46 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct ConnectorStateFfiResultClientConnectorStateTypeBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal ClientConnectorStateType ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe ClientConnectorStateType Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorStateFfiResultU16BoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorStateFfiResultU16BoxIronRdpError.cs new file mode 100644 index 000000000..d5d3402c8 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorStateFfiResultU16BoxIronRdpError.cs @@ -0,0 +1,46 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct ConnectorStateFfiResultU16BoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal ushort ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe ushort Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawLicenseExchangeSequence.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawLicenseExchangeSequence.cs new file mode 100644 index 000000000..a0d756681 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawLicenseExchangeSequence.cs @@ -0,0 +1,21 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct LicenseExchangeSequence +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LicenseExchangeSequence_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(LicenseExchangeSequence* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawSecurityProtocol.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawSecurityProtocol.cs new file mode 100644 index 000000000..d3832a261 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawSecurityProtocol.cs @@ -0,0 +1,21 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct SecurityProtocol +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SecurityProtocol_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(SecurityProtocol* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/SecurityProtocol.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/SecurityProtocol.cs new file mode 100644 index 000000000..92dec8315 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/SecurityProtocol.cs @@ -0,0 +1,63 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp; + +#nullable enable + +public partial class SecurityProtocol: IDisposable +{ + private unsafe Raw.SecurityProtocol* _inner; + + /// + /// Creates a managed SecurityProtocol from a raw handle. + /// + /// + /// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free). + ///
+ /// This constructor assumes the raw struct is allocated on Rust side. + /// If implemented, the custom Drop implementation on Rust side WILL run on destruction. + ///
+ public unsafe SecurityProtocol(Raw.SecurityProtocol* handle) + { + _inner = handle; + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.SecurityProtocol* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.SecurityProtocol.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~SecurityProtocol() + { + Dispose(); + } +} From d829e56931f79e02a134161a26536b89722e705f Mon Sep 17 00:00:00 2001 From: irving ou Date: Fri, 5 Apr 2024 16:00:33 -0400 Subject: [PATCH 04/18] WIP:added part of active stage --- ffi/Cargo.toml | 2 +- .../Devolutions.IronRdp/Generated/Action.cs | 63 +++++ .../Generated/ActiveStage.cs | 38 +++ .../Generated/ActiveStageOutput.cs | 255 ++++++++++++++++++ .../Generated/ActiveStageOutputIterator.cs | 96 +++++++ .../Generated/ActiveStageOutputType.cs | 24 ++ .../Generated/BytesArray.cs | 105 ++++++++ .../Generated/DecodedImage.cs | 87 ++++++ .../Generated/DecodedPointer.cs | 171 ++++++++++++ .../Generated/GracefulDisconnectReason.cs | 63 +++++ .../Generated/InclusiveRectangle.cs | 63 +++++ .../Generated/IronRdpPdu.cs | 93 +++++++ .../Devolutions.IronRdp/Generated/PduInfo.cs | 108 ++++++++ .../Devolutions.IronRdp/Generated/Position.cs | 105 ++++++++ .../Generated/RawAction.cs | 21 ++ .../Generated/RawActiveStage.cs | 3 + .../Generated/RawActiveStageOutput.cs | 42 +++ .../Generated/RawActiveStageOutputIterator.cs | 27 ++ .../Generated/RawActiveStageOutputType.cs | 24 ++ .../Generated/RawBytesArray.cs | 27 ++ .../Generated/RawDecodedImage.cs | 24 ++ .../Generated/RawDecodedPointer.cs | 36 +++ .../Generated/RawGracefulDisconnectReason.cs | 21 ++ .../Generated/RawInclusiveRectangle.cs | 21 ++ .../Generated/RawIronRdpPdu.cs | 24 ++ ...duFfiResultOptBoxPduInfoBoxIronRdpError.cs | 46 ++++ .../Generated/RawPduInfo.cs | 27 ++ .../Generated/RawPosition.cs | 27 ++ ...ctiveStageOutputIteratorBoxIronRdpError.cs | 46 ++++ ffi/src/connector/mod.rs | 2 +- ffi/src/error.rs | 11 +- ffi/src/graphics.rs | 32 +++ ffi/src/lib.rs | 1 + ffi/src/pdu.rs | 30 +++ ffi/src/session/image.rs | 15 ++ ffi/src/session/mod.rs | 113 +++++++- ffi/src/utils/mod.rs | 34 +++ 37 files changed, 1923 insertions(+), 4 deletions(-) create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/Action.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStageOutput.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStageOutputIterator.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStageOutputType.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/BytesArray.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/DecodedImage.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/DecodedPointer.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/GracefulDisconnectReason.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/InclusiveRectangle.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/IronRdpPdu.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/PduInfo.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/Position.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawAction.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStageOutput.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStageOutputIterator.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStageOutputType.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawBytesArray.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawDecodedImage.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawDecodedPointer.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawGracefulDisconnectReason.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawInclusiveRectangle.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawIronRdpPdu.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawPduFfiResultOptBoxPduInfoBoxIronRdpError.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawPduInfo.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawPosition.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxActiveStageOutputIteratorBoxIronRdpError.cs create mode 100644 ffi/src/graphics.rs create mode 100644 ffi/src/session/image.rs diff --git a/ffi/Cargo.toml b/ffi/Cargo.toml index a38846d2b..2604117bb 100644 --- a/ffi/Cargo.toml +++ b/ffi/Cargo.toml @@ -19,7 +19,7 @@ doctest = false [dependencies] diplomat = "0.7.0" diplomat-runtime = "0.7.0" -ironrdp = { workspace = true, features = ["connector", "dvc", "svc","rdpdr","rdpsnd"] } +ironrdp = { workspace = true, features = ["connector", "dvc", "svc","rdpdr","rdpsnd","graphics"] } sspi = { workspace = true, features = ["network_client"] } thiserror.workspace = true diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/Action.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/Action.cs new file mode 100644 index 000000000..d83abd39e --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/Action.cs @@ -0,0 +1,63 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp; + +#nullable enable + +public partial class Action: IDisposable +{ + private unsafe Raw.Action* _inner; + + /// + /// Creates a managed Action from a raw handle. + /// + /// + /// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free). + ///
+ /// This constructor assumes the raw struct is allocated on Rust side. + /// If implemented, the custom Drop implementation on Rust side WILL run on destruction. + ///
+ public unsafe Action(Raw.Action* handle) + { + _inner = handle; + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.Action* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.Action.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~Action() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStage.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStage.cs index 641df3e6c..7770d1b62 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStage.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStage.cs @@ -29,6 +29,44 @@ public unsafe ActiveStage(Raw.ActiveStage* handle) _inner = handle; } + /// + /// + /// A ActiveStageOutputIterator allocated on Rust side. + /// + public ActiveStageOutputIterator Process(DecodedImage image, Action action, byte[] payload) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ActiveStage"); + } + nuint payloadLength = (nuint)payload.Length; + Raw.DecodedImage* imageRaw; + imageRaw = image.AsFFI(); + if (imageRaw == null) + { + throw new ObjectDisposedException("DecodedImage"); + } + Raw.Action* actionRaw; + actionRaw = action.AsFFI(); + if (actionRaw == null) + { + throw new ObjectDisposedException("Action"); + } + fixed (byte* payloadPtr = payload) + { + Raw.SessionFfiResultBoxActiveStageOutputIteratorBoxIronRdpError result = Raw.ActiveStage.Process(_inner, imageRaw, actionRaw, payloadPtr, payloadLength); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.ActiveStageOutputIterator* retVal = result.Ok; + return new ActiveStageOutputIterator(retVal); + } + } + } + /// /// Returns the underlying raw handle. /// diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStageOutput.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStageOutput.cs new file mode 100644 index 000000000..1f195ca92 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStageOutput.cs @@ -0,0 +1,255 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp; + +#nullable enable + +public partial class ActiveStageOutput: IDisposable +{ + private unsafe Raw.ActiveStageOutput* _inner; + + public ConnectionActivationSequence? DeactivateAll + { + get + { + return GetDeactivateAll(); + } + } + + public InclusiveRectangle? GraphicsUpdate + { + get + { + return GetGraphicsUpdate(); + } + } + + public DecodedPointer? PointerButmap + { + get + { + return GetPointerButmap(); + } + } + + public Position? PointerPosition + { + get + { + return GetPointerPosition(); + } + } + + public BytesArray? ResponseFrame + { + get + { + return GetResponseFrame(); + } + } + + public GracefulDisconnectReason? Terminate + { + get + { + return GetTerminate(); + } + } + + public ActiveStageOutputType Type + { + get + { + return GetType(); + } + } + + /// + /// Creates a managed ActiveStageOutput from a raw handle. + /// + /// + /// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free). + ///
+ /// This constructor assumes the raw struct is allocated on Rust side. + /// If implemented, the custom Drop implementation on Rust side WILL run on destruction. + ///
+ public unsafe ActiveStageOutput(Raw.ActiveStageOutput* handle) + { + _inner = handle; + } + + /// + /// A ActiveStageOutputType allocated on C# side. + /// + public ActiveStageOutputType GetType() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ActiveStageOutput"); + } + Raw.ActiveStageOutputType retVal = Raw.ActiveStageOutput.GetType(_inner); + return (ActiveStageOutputType)retVal; + } + } + + /// + /// A BytesArray allocated on Rust side. + /// + public BytesArray? GetResponseFrame() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ActiveStageOutput"); + } + Raw.BytesArray* retVal = Raw.ActiveStageOutput.GetResponseFrame(_inner); + if (retVal == null) + { + return null; + } + return new BytesArray(retVal); + } + } + + /// + /// A InclusiveRectangle allocated on Rust side. + /// + public InclusiveRectangle? GetGraphicsUpdate() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ActiveStageOutput"); + } + Raw.InclusiveRectangle* retVal = Raw.ActiveStageOutput.GetGraphicsUpdate(_inner); + if (retVal == null) + { + return null; + } + return new InclusiveRectangle(retVal); + } + } + + /// + /// A Position allocated on Rust side. + /// + public Position? GetPointerPosition() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ActiveStageOutput"); + } + Raw.Position* retVal = Raw.ActiveStageOutput.GetPointerPosition(_inner); + if (retVal == null) + { + return null; + } + return new Position(retVal); + } + } + + /// + /// A DecodedPointer allocated on Rust side. + /// + public DecodedPointer? GetPointerButmap() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ActiveStageOutput"); + } + Raw.DecodedPointer* retVal = Raw.ActiveStageOutput.GetPointerButmap(_inner); + if (retVal == null) + { + return null; + } + return new DecodedPointer(retVal); + } + } + + /// + /// A GracefulDisconnectReason allocated on Rust side. + /// + public GracefulDisconnectReason? GetTerminate() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ActiveStageOutput"); + } + Raw.GracefulDisconnectReason* retVal = Raw.ActiveStageOutput.GetTerminate(_inner); + if (retVal == null) + { + return null; + } + return new GracefulDisconnectReason(retVal); + } + } + + /// + /// A ConnectionActivationSequence allocated on Rust side. + /// + public ConnectionActivationSequence? GetDeactivateAll() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ActiveStageOutput"); + } + Raw.ConnectionActivationSequence* retVal = Raw.ActiveStageOutput.GetDeactivateAll(_inner); + if (retVal == null) + { + return null; + } + return new ConnectionActivationSequence(retVal); + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.ActiveStageOutput* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.ActiveStageOutput.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~ActiveStageOutput() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStageOutputIterator.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStageOutputIterator.cs new file mode 100644 index 000000000..b8f02de2b --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStageOutputIterator.cs @@ -0,0 +1,96 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp; + +#nullable enable + +public partial class ActiveStageOutputIterator: IDisposable +{ + private unsafe Raw.ActiveStageOutputIterator* _inner; + + /// + /// Creates a managed ActiveStageOutputIterator from a raw handle. + /// + /// + /// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free). + ///
+ /// This constructor assumes the raw struct is allocated on Rust side. + /// If implemented, the custom Drop implementation on Rust side WILL run on destruction. + ///
+ public unsafe ActiveStageOutputIterator(Raw.ActiveStageOutputIterator* handle) + { + _inner = handle; + } + + public nuint Len() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ActiveStageOutputIterator"); + } + nuint retVal = Raw.ActiveStageOutputIterator.Len(_inner); + return retVal; + } + } + + /// + /// A ActiveStageOutput allocated on Rust side. + /// + public ActiveStageOutput? Next() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ActiveStageOutputIterator"); + } + Raw.ActiveStageOutput* retVal = Raw.ActiveStageOutputIterator.Next(_inner); + if (retVal == null) + { + return null; + } + return new ActiveStageOutput(retVal); + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.ActiveStageOutputIterator* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.ActiveStageOutputIterator.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~ActiveStageOutputIterator() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStageOutputType.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStageOutputType.cs new file mode 100644 index 000000000..e4763bd9e --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStageOutputType.cs @@ -0,0 +1,24 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp; + +#nullable enable + +public enum ActiveStageOutputType +{ + ResponseFrame = 0, + GraphicsUpdate = 1, + PointerDefault = 2, + PointerHidden = 3, + PointerPosition = 4, + PointerBitmap = 5, + Terminate = 6, + DeactivateAll = 7, +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/BytesArray.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/BytesArray.cs new file mode 100644 index 000000000..2a342e2d2 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/BytesArray.cs @@ -0,0 +1,105 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp; + +#nullable enable + +public partial class BytesArray: IDisposable +{ + private unsafe Raw.BytesArray* _inner; + + public nuint Size + { + get + { + return GetSize(); + } + } + + /// + /// Creates a managed BytesArray from a raw handle. + /// + /// + /// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free). + ///
+ /// This constructor assumes the raw struct is allocated on Rust side. + /// If implemented, the custom Drop implementation on Rust side WILL run on destruction. + ///
+ public unsafe BytesArray(Raw.BytesArray* handle) + { + _inner = handle; + } + + public nuint GetSize() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("BytesArray"); + } + nuint retVal = Raw.BytesArray.GetSize(_inner); + return retVal; + } + } + + /// + public void Fill(byte[] buffer) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("BytesArray"); + } + nuint bufferLength = (nuint)buffer.Length; + fixed (byte* bufferPtr = buffer) + { + Raw.UtilsFfiResultVoidBoxIronRdpError result = Raw.BytesArray.Fill(_inner, bufferPtr, bufferLength); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + } + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.BytesArray* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.BytesArray.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~BytesArray() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/DecodedImage.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/DecodedImage.cs new file mode 100644 index 000000000..c3a06e36c --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/DecodedImage.cs @@ -0,0 +1,87 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp; + +#nullable enable + +public partial class DecodedImage: IDisposable +{ + private unsafe Raw.DecodedImage* _inner; + + public BytesArray Data + { + get + { + return GetData(); + } + } + + /// + /// Creates a managed DecodedImage from a raw handle. + /// + /// + /// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free). + ///
+ /// This constructor assumes the raw struct is allocated on Rust side. + /// If implemented, the custom Drop implementation on Rust side WILL run on destruction. + ///
+ public unsafe DecodedImage(Raw.DecodedImage* handle) + { + _inner = handle; + } + + /// + /// A BytesArray allocated on Rust side. + /// + public BytesArray GetData() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("DecodedImage"); + } + Raw.BytesArray* retVal = Raw.DecodedImage.GetData(_inner); + return new BytesArray(retVal); + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.DecodedImage* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.DecodedImage.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~DecodedImage() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/DecodedPointer.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/DecodedPointer.cs new file mode 100644 index 000000000..3b0aa90c0 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/DecodedPointer.cs @@ -0,0 +1,171 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp; + +#nullable enable + +public partial class DecodedPointer: IDisposable +{ + private unsafe Raw.DecodedPointer* _inner; + + public BytesArray Data + { + get + { + return GetData(); + } + } + + public ushort Height + { + get + { + return GetHeight(); + } + } + + public ushort HotspotX + { + get + { + return GetHotspotX(); + } + } + + public ushort HotspotY + { + get + { + return GetHotspotY(); + } + } + + public ushort Width + { + get + { + return GetWidth(); + } + } + + /// + /// Creates a managed DecodedPointer from a raw handle. + /// + /// + /// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free). + ///
+ /// This constructor assumes the raw struct is allocated on Rust side. + /// If implemented, the custom Drop implementation on Rust side WILL run on destruction. + ///
+ public unsafe DecodedPointer(Raw.DecodedPointer* handle) + { + _inner = handle; + } + + public ushort GetWidth() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("DecodedPointer"); + } + ushort retVal = Raw.DecodedPointer.GetWidth(_inner); + return retVal; + } + } + + public ushort GetHeight() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("DecodedPointer"); + } + ushort retVal = Raw.DecodedPointer.GetHeight(_inner); + return retVal; + } + } + + public ushort GetHotspotX() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("DecodedPointer"); + } + ushort retVal = Raw.DecodedPointer.GetHotspotX(_inner); + return retVal; + } + } + + public ushort GetHotspotY() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("DecodedPointer"); + } + ushort retVal = Raw.DecodedPointer.GetHotspotY(_inner); + return retVal; + } + } + + /// + /// A BytesArray allocated on Rust side. + /// + public BytesArray GetData() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("DecodedPointer"); + } + Raw.BytesArray* retVal = Raw.DecodedPointer.GetData(_inner); + return new BytesArray(retVal); + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.DecodedPointer* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.DecodedPointer.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~DecodedPointer() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/GracefulDisconnectReason.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/GracefulDisconnectReason.cs new file mode 100644 index 000000000..8e8c22a5d --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/GracefulDisconnectReason.cs @@ -0,0 +1,63 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp; + +#nullable enable + +public partial class GracefulDisconnectReason: IDisposable +{ + private unsafe Raw.GracefulDisconnectReason* _inner; + + /// + /// Creates a managed GracefulDisconnectReason from a raw handle. + /// + /// + /// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free). + ///
+ /// This constructor assumes the raw struct is allocated on Rust side. + /// If implemented, the custom Drop implementation on Rust side WILL run on destruction. + ///
+ public unsafe GracefulDisconnectReason(Raw.GracefulDisconnectReason* handle) + { + _inner = handle; + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.GracefulDisconnectReason* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.GracefulDisconnectReason.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~GracefulDisconnectReason() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/InclusiveRectangle.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/InclusiveRectangle.cs new file mode 100644 index 000000000..3ffb403c8 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/InclusiveRectangle.cs @@ -0,0 +1,63 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp; + +#nullable enable + +public partial class InclusiveRectangle: IDisposable +{ + private unsafe Raw.InclusiveRectangle* _inner; + + /// + /// Creates a managed InclusiveRectangle from a raw handle. + /// + /// + /// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free). + ///
+ /// This constructor assumes the raw struct is allocated on Rust side. + /// If implemented, the custom Drop implementation on Rust side WILL run on destruction. + ///
+ public unsafe InclusiveRectangle(Raw.InclusiveRectangle* handle) + { + _inner = handle; + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.InclusiveRectangle* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.InclusiveRectangle.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~InclusiveRectangle() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/IronRdpPdu.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/IronRdpPdu.cs new file mode 100644 index 000000000..c80c47ac2 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/IronRdpPdu.cs @@ -0,0 +1,93 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp; + +#nullable enable + +public partial class IronRdpPdu: IDisposable +{ + private unsafe Raw.IronRdpPdu* _inner; + + /// + /// Creates a managed IronRdpPdu from a raw handle. + /// + /// + /// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free). + ///
+ /// This constructor assumes the raw struct is allocated on Rust side. + /// If implemented, the custom Drop implementation on Rust side WILL run on destruction. + ///
+ public unsafe IronRdpPdu(Raw.IronRdpPdu* handle) + { + _inner = handle; + } + + /// + /// + /// A PduInfo allocated on Rust side. + /// + public PduInfo FindSize(byte[] bytes) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("IronRdpPdu"); + } + nuint bytesLength = (nuint)bytes.Length; + fixed (byte* bytesPtr = bytes) + { + Raw.PduFfiResultOptBoxPduInfoBoxIronRdpError result = Raw.IronRdpPdu.FindSize(_inner, bytesPtr, bytesLength); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.PduInfo* retVal = result.Ok; + if (retVal == null) + { + return null; + } + return new PduInfo(retVal); + } + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.IronRdpPdu* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.IronRdpPdu.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~IronRdpPdu() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/PduInfo.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/PduInfo.cs new file mode 100644 index 000000000..94ce1093b --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/PduInfo.cs @@ -0,0 +1,108 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp; + +#nullable enable + +public partial class PduInfo: IDisposable +{ + private unsafe Raw.PduInfo* _inner; + + public Action Action + { + get + { + return GetAction(); + } + } + + public nuint Length + { + get + { + return GetLength(); + } + } + + /// + /// Creates a managed PduInfo from a raw handle. + /// + /// + /// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free). + ///
+ /// This constructor assumes the raw struct is allocated on Rust side. + /// If implemented, the custom Drop implementation on Rust side WILL run on destruction. + ///
+ public unsafe PduInfo(Raw.PduInfo* handle) + { + _inner = handle; + } + + /// + /// A Action allocated on Rust side. + /// + public Action GetAction() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("PduInfo"); + } + Raw.Action* retVal = Raw.PduInfo.GetAction(_inner); + return new Action(retVal); + } + } + + public nuint GetLength() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("PduInfo"); + } + nuint retVal = Raw.PduInfo.GetLength(_inner); + return retVal; + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.PduInfo* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.PduInfo.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~PduInfo() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/Position.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/Position.cs new file mode 100644 index 000000000..7e8f6d860 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/Position.cs @@ -0,0 +1,105 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp; + +#nullable enable + +public partial class Position: IDisposable +{ + private unsafe Raw.Position* _inner; + + public ushort X + { + get + { + return GetX(); + } + } + + public ushort Y + { + get + { + return GetY(); + } + } + + /// + /// Creates a managed Position from a raw handle. + /// + /// + /// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free). + ///
+ /// This constructor assumes the raw struct is allocated on Rust side. + /// If implemented, the custom Drop implementation on Rust side WILL run on destruction. + ///
+ public unsafe Position(Raw.Position* handle) + { + _inner = handle; + } + + public ushort GetX() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("Position"); + } + ushort retVal = Raw.Position.GetX(_inner); + return retVal; + } + } + + public ushort GetY() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("Position"); + } + ushort retVal = Raw.Position.GetY(_inner); + return retVal; + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.Position* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.Position.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~Position() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawAction.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawAction.cs new file mode 100644 index 000000000..87c5a1e26 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawAction.cs @@ -0,0 +1,21 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct Action +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Action_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(Action* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStage.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStage.cs index 40298f76e..c0b5e9116 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStage.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStage.cs @@ -16,6 +16,9 @@ public partial struct ActiveStage { private const string NativeLib = "DevolutionsIronRdp"; + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStage_process", ExactSpelling = true)] + public static unsafe extern SessionFfiResultBoxActiveStageOutputIteratorBoxIronRdpError Process(ActiveStage* self, DecodedImage* image, Action* action, byte* payload, nuint payloadSz); + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStage_destroy", ExactSpelling = true)] public static unsafe extern void Destroy(ActiveStage* self); } diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStageOutput.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStageOutput.cs new file mode 100644 index 000000000..912422222 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStageOutput.cs @@ -0,0 +1,42 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct ActiveStageOutput +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStageOutput_get_type", ExactSpelling = true)] + public static unsafe extern ActiveStageOutputType GetType(ActiveStageOutput* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStageOutput_get_response_frame", ExactSpelling = true)] + public static unsafe extern BytesArray* GetResponseFrame(ActiveStageOutput* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStageOutput_get_graphics_update", ExactSpelling = true)] + public static unsafe extern InclusiveRectangle* GetGraphicsUpdate(ActiveStageOutput* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStageOutput_get_pointer_position", ExactSpelling = true)] + public static unsafe extern Position* GetPointerPosition(ActiveStageOutput* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStageOutput_get_pointer_butmap", ExactSpelling = true)] + public static unsafe extern DecodedPointer* GetPointerButmap(ActiveStageOutput* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStageOutput_get_terminate", ExactSpelling = true)] + public static unsafe extern GracefulDisconnectReason* GetTerminate(ActiveStageOutput* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStageOutput_get_deactivate_all", ExactSpelling = true)] + public static unsafe extern ConnectionActivationSequence* GetDeactivateAll(ActiveStageOutput* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStageOutput_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(ActiveStageOutput* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStageOutputIterator.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStageOutputIterator.cs new file mode 100644 index 000000000..ef95053ac --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStageOutputIterator.cs @@ -0,0 +1,27 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct ActiveStageOutputIterator +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStageOutputIterator_len", ExactSpelling = true)] + public static unsafe extern nuint Len(ActiveStageOutputIterator* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStageOutputIterator_next", ExactSpelling = true)] + public static unsafe extern ActiveStageOutput* Next(ActiveStageOutputIterator* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStageOutputIterator_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(ActiveStageOutputIterator* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStageOutputType.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStageOutputType.cs new file mode 100644 index 000000000..5f05f2f44 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStageOutputType.cs @@ -0,0 +1,24 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +public enum ActiveStageOutputType +{ + ResponseFrame = 0, + GraphicsUpdate = 1, + PointerDefault = 2, + PointerHidden = 3, + PointerPosition = 4, + PointerBitmap = 5, + Terminate = 6, + DeactivateAll = 7, +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawBytesArray.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawBytesArray.cs new file mode 100644 index 000000000..dd2955500 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawBytesArray.cs @@ -0,0 +1,27 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct BytesArray +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "BytesArray_get_size", ExactSpelling = true)] + public static unsafe extern nuint GetSize(BytesArray* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "BytesArray_fill", ExactSpelling = true)] + public static unsafe extern UtilsFfiResultVoidBoxIronRdpError Fill(BytesArray* self, byte* buffer, nuint bufferSz); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "BytesArray_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(BytesArray* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawDecodedImage.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawDecodedImage.cs new file mode 100644 index 000000000..bc6e0e8f7 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawDecodedImage.cs @@ -0,0 +1,24 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct DecodedImage +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DecodedImage_get_data", ExactSpelling = true)] + public static unsafe extern BytesArray* GetData(DecodedImage* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DecodedImage_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(DecodedImage* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawDecodedPointer.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawDecodedPointer.cs new file mode 100644 index 000000000..fc7f0485e --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawDecodedPointer.cs @@ -0,0 +1,36 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct DecodedPointer +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DecodedPointer_get_width", ExactSpelling = true)] + public static unsafe extern ushort GetWidth(DecodedPointer* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DecodedPointer_get_height", ExactSpelling = true)] + public static unsafe extern ushort GetHeight(DecodedPointer* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DecodedPointer_get_hotspot_x", ExactSpelling = true)] + public static unsafe extern ushort GetHotspotX(DecodedPointer* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DecodedPointer_get_hotspot_y", ExactSpelling = true)] + public static unsafe extern ushort GetHotspotY(DecodedPointer* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DecodedPointer_get_data", ExactSpelling = true)] + public static unsafe extern BytesArray* GetData(DecodedPointer* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DecodedPointer_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(DecodedPointer* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawGracefulDisconnectReason.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawGracefulDisconnectReason.cs new file mode 100644 index 000000000..8539b037d --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawGracefulDisconnectReason.cs @@ -0,0 +1,21 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct GracefulDisconnectReason +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "GracefulDisconnectReason_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(GracefulDisconnectReason* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawInclusiveRectangle.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawInclusiveRectangle.cs new file mode 100644 index 000000000..6215e5924 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawInclusiveRectangle.cs @@ -0,0 +1,21 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct InclusiveRectangle +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "InclusiveRectangle_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(InclusiveRectangle* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawIronRdpPdu.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawIronRdpPdu.cs new file mode 100644 index 000000000..32a59b2f3 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawIronRdpPdu.cs @@ -0,0 +1,24 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct IronRdpPdu +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "IronRdpPdu_find_size", ExactSpelling = true)] + public static unsafe extern PduFfiResultOptBoxPduInfoBoxIronRdpError FindSize(IronRdpPdu* self, byte* bytes, nuint bytesSz); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "IronRdpPdu_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(IronRdpPdu* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawPduFfiResultOptBoxPduInfoBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawPduFfiResultOptBoxPduInfoBoxIronRdpError.cs new file mode 100644 index 000000000..4e6f63cd7 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawPduFfiResultOptBoxPduInfoBoxIronRdpError.cs @@ -0,0 +1,46 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct PduFfiResultOptBoxPduInfoBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal PduInfo* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe PduInfo* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawPduInfo.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawPduInfo.cs new file mode 100644 index 000000000..04488e485 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawPduInfo.cs @@ -0,0 +1,27 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct PduInfo +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PduInfo_get_action", ExactSpelling = true)] + public static unsafe extern Action* GetAction(PduInfo* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PduInfo_get_length", ExactSpelling = true)] + public static unsafe extern nuint GetLength(PduInfo* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PduInfo_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(PduInfo* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawPosition.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawPosition.cs new file mode 100644 index 000000000..b3ed2ce02 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawPosition.cs @@ -0,0 +1,27 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct Position +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Position_get_x", ExactSpelling = true)] + public static unsafe extern ushort GetX(Position* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Position_get_y", ExactSpelling = true)] + public static unsafe extern ushort GetY(Position* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Position_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(Position* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxActiveStageOutputIteratorBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxActiveStageOutputIteratorBoxIronRdpError.cs new file mode 100644 index 000000000..d31234405 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxActiveStageOutputIteratorBoxIronRdpError.cs @@ -0,0 +1,46 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct SessionFfiResultBoxActiveStageOutputIteratorBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal ActiveStageOutputIterator* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe ActiveStageOutputIterator* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/src/connector/mod.rs b/ffi/src/connector/mod.rs index f76f262f3..633282a75 100644 --- a/ffi/src/connector/mod.rs +++ b/ffi/src/connector/mod.rs @@ -169,5 +169,5 @@ pub mod ffi { pub struct LicenseExchangeSequence(pub ironrdp::connector::LicenseExchangeSequence); #[diplomat::opaque] - pub struct ConnectionActivationSequence(pub ironrdp::connector::connection_activation::ConnectionActivationSequence); + pub struct ConnectionActivationSequence(pub Box); } diff --git a/ffi/src/error.rs b/ffi/src/error.rs index 3e0de3219..9b6365b56 100644 --- a/ffi/src/error.rs +++ b/ffi/src/error.rs @@ -1,7 +1,7 @@ #![allow(clippy::return_self_not_must_use)] use std::fmt::Display; -use ironrdp::connector::ConnectorError; +use ironrdp::{connector::ConnectorError, session::SessionError}; use self::ffi::IronRdpErrorKind; @@ -46,6 +46,15 @@ impl From for IronRdpErrorKind { } } +impl From for IronRdpErrorKind { + fn from(value: SessionError) -> Self { + match value.kind() { + ironrdp::session::SessionErrorKind::Pdu(_) => IronRdpErrorKind::PduError, + _ => IronRdpErrorKind::Generic, + } + } +} + impl From for Box where T: Into + ToString, diff --git a/ffi/src/graphics.rs b/ffi/src/graphics.rs new file mode 100644 index 000000000..22c9e1e7c --- /dev/null +++ b/ffi/src/graphics.rs @@ -0,0 +1,32 @@ + +#[diplomat::bridge] +pub mod ffi { + use std::rc::Rc; + + use crate::utils::ffi::BytesArray; + + #[diplomat::opaque] + pub struct DecodedPointer(pub Rc); + + impl DecodedPointer { + pub fn get_width(&self) -> u16 { + self.0.width + } + + pub fn get_height(&self) -> u16 { + self.0.height + } + + pub fn get_hotspot_x(&self) -> u16 { + self.0.hotspot_x + } + + pub fn get_hotspot_y(&self) -> u16 { + self.0.hotspot_y + } + + pub fn get_data<'a>(&'a self) -> Box> { + Box::new(BytesArray(&self.0.bitmap_data)) + } + } +} \ No newline at end of file diff --git a/ffi/src/lib.rs b/ffi/src/lib.rs index ff2e013c9..3b4c1af1b 100644 --- a/ffi/src/lib.rs +++ b/ffi/src/lib.rs @@ -8,3 +8,4 @@ pub mod pdu; pub mod svc; pub mod utils; pub mod session; +pub mod graphics; \ No newline at end of file diff --git a/ffi/src/pdu.rs b/ffi/src/pdu.rs index 5302986d1..776755410 100644 --- a/ffi/src/pdu.rs +++ b/ffi/src/pdu.rs @@ -1,6 +1,8 @@ #[diplomat::bridge] pub mod ffi { + use ironrdp::pdu::Pdu; + use crate::error::ffi::IronRdpError; #[diplomat::opaque] @@ -26,4 +28,32 @@ pub mod ffi { #[diplomat::opaque] pub struct ConnectInitial(pub ironrdp::pdu::mcs::ConnectInitial); + + #[diplomat::opaque] + pub struct InclusiveRectangle(pub ironrdp::pdu::geometry::InclusiveRectangle); + + #[diplomat::opaque] + pub struct IronRdpPdu; // A struct representing the ironrdp_pdu crate + + #[diplomat::opaque] + pub struct PduInfo(pub ironrdp::pdu::PduInfo); + + impl PduInfo { + pub fn get_action(&self) -> Box { + Box::new(Action(self.0.action)) + } + + pub fn get_length(&self) -> usize { + self.0.length + } + } + + #[diplomat::opaque] + pub struct Action(pub ironrdp::pdu::Action); + + impl IronRdpPdu { + pub fn find_size(&self, bytes: &[u8]) -> Result>, Box> { + Ok(ironrdp::pdu::find_size(bytes)?.map(PduInfo).map(Box::new)) + } + } } diff --git a/ffi/src/session/image.rs b/ffi/src/session/image.rs new file mode 100644 index 000000000..1120c8285 --- /dev/null +++ b/ffi/src/session/image.rs @@ -0,0 +1,15 @@ +#[diplomat::bridge] +pub mod ffi { + use crate::utils::ffi::BytesArray; + + + #[diplomat::opaque] + pub struct DecodedImage<'a>(pub &'a mut ironrdp::session::image::DecodedImage); + + impl<'a> DecodedImage<'a> { + // The bytes array lives as long as the DecodedImage + pub fn get_data(&'a self) -> Box>{ + Box::new(BytesArray(self.0.data())) + } + } +} \ No newline at end of file diff --git a/ffi/src/session/mod.rs b/ffi/src/session/mod.rs index 96299bbba..368a86d94 100644 --- a/ffi/src/session/mod.rs +++ b/ffi/src/session/mod.rs @@ -1,7 +1,118 @@ +pub mod image; #[diplomat::bridge] pub mod ffi { + use crate::{ + connector::ffi::ConnectionActivationSequence, error::ffi::IronRdpError, graphics::ffi::DecodedPointer, pdu::ffi::{Action, InclusiveRectangle}, utils::ffi::{BytesArray, Position} + }; + + use super::image::ffi::DecodedImage; + #[diplomat::opaque] pub struct ActiveStage(pub ironrdp::session::ActiveStage); -} \ No newline at end of file + + #[diplomat::opaque] + pub struct ActiveStageOutput(pub ironrdp::session::ActiveStageOutput); + + #[diplomat::opaque] + pub struct ActiveStageOutputIterator(pub Vec); + + impl ActiveStageOutputIterator { + pub fn len(&self) -> usize { + self.0.len() + } + + pub fn next(&mut self) -> Option> { + self.0.pop().map(ActiveStageOutput).map(Box::new) + } + } + + impl ActiveStage { + pub fn process( + &mut self, + image: &mut DecodedImage, + action: &Action, + payload: &[u8], + ) -> Result, Box> { + let outputs = self.0.process(image.0, action.0, payload)?; + Ok(Box::new(ActiveStageOutputIterator(outputs))) + } + } + + pub enum ActiveStageOutputType { + ResponseFrame, + GraphicsUpdate, + PointerDefault, + PointerHidden, + PointerPosition, + PointerBitmap, + Terminate, + DeactivateAll, + } + + impl ActiveStageOutput { + pub fn get_type(&self) -> ActiveStageOutputType { + match &self.0 { + ironrdp::session::ActiveStageOutput::ResponseFrame { .. } => ActiveStageOutputType::ResponseFrame, + ironrdp::session::ActiveStageOutput::GraphicsUpdate { .. } => ActiveStageOutputType::GraphicsUpdate, + ironrdp::session::ActiveStageOutput::PointerDefault { .. } => ActiveStageOutputType::PointerDefault, + ironrdp::session::ActiveStageOutput::PointerHidden { .. } => ActiveStageOutputType::PointerHidden, + ironrdp::session::ActiveStageOutput::PointerPosition { .. } => ActiveStageOutputType::PointerPosition, + ironrdp::session::ActiveStageOutput::PointerBitmap { .. } => ActiveStageOutputType::PointerBitmap, + ironrdp::session::ActiveStageOutput::Terminate { .. } => ActiveStageOutputType::Terminate, + ironrdp::session::ActiveStageOutput::DeactivateAll { .. } => ActiveStageOutputType::DeactivateAll, + } + } + + pub fn get_response_frame<'a>(&'a self) -> Option>> { + match &self.0 { + ironrdp::session::ActiveStageOutput::ResponseFrame(frame) => Some(Box::new(BytesArray(frame))), + _ => None, + } + } + + pub fn get_graphics_update(&self) -> Option> { + match &self.0 { + ironrdp::session::ActiveStageOutput::GraphicsUpdate(rect) => { + Some(Box::new(InclusiveRectangle(rect.clone()))) + } + _ => None, + } + } + + pub fn get_pointer_position(&self) -> Option> { + match &self.0 { + ironrdp::session::ActiveStageOutput::PointerPosition { x, y } => Some(Position { x: *x, y: *y }), + _ => None, + } + .map(Box::new) + } + + pub fn get_pointer_butmap(&self) -> Option> { + match &self.0 { + ironrdp::session::ActiveStageOutput::PointerBitmap(decoded_pointer) => { + Some(DecodedPointer(decoded_pointer.clone())) + } + _ => None, + }.map(Box::new) + } + + pub fn get_terminate(&self) -> Option> { + match &self.0 { + ironrdp::session::ActiveStageOutput::Terminate(reason) => Some(GracefulDisconnectReason(reason.clone())), + _ => None, + }.map(Box::new) + } + + pub fn get_deactivate_all(&self) -> Option> { + match &self.0 { + ironrdp::session::ActiveStageOutput::DeactivateAll(cas) => Some(ConnectionActivationSequence(cas.clone())), + _ => None, + }.map(Box::new) + } + } + + #[diplomat::opaque] + pub struct GracefulDisconnectReason(pub ironrdp::session::GracefulDisconnectReason); +} diff --git a/ffi/src/utils/mod.rs b/ffi/src/utils/mod.rs index 6ede3dae6..6694893a5 100644 --- a/ffi/src/utils/mod.rs +++ b/ffi/src/utils/mod.rs @@ -28,6 +28,40 @@ pub mod ffi { } } + #[diplomat::opaque] + pub struct BytesArray<'a>(pub &'a [u8]); + + impl<'a> BytesArray<'a> { + pub fn get_size(&'a self) -> usize { + self.0.len() + } + + pub fn fill(&'a self, buffer: &'a mut [u8]) -> Result<(), Box> { + if buffer.len() < self.0.len() { + return Err("Buffer is too small".into()); + } + buffer.copy_from_slice(&self.0); + Ok(()) + } + + } + + #[diplomat::opaque] + pub struct Position{ + pub x: u16, + pub y: u16 + } + + impl Position { + pub fn get_x(&self) -> u16 { + self.x + } + + pub fn get_y(&self) -> u16 { + self.y + } + } + #[diplomat::opaque] pub struct OptionalUsize(pub Option); From 7832ea4a203c2fcda2fdd001de43a59438bf14ab Mon Sep 17 00:00:00 2001 From: irving ou Date: Fri, 5 Apr 2024 16:33:24 -0400 Subject: [PATCH 05/18] WIP:added part 2 of active stage --- ffi/Cargo.toml | 2 +- .../Generated/ActiveStageOutput.cs | 10 +- .../{BytesArray.cs => BytesSlice.cs} | 22 ++-- .../Devolutions.IronRdp/Generated/Database.cs | 75 +++++++++++++ .../Generated/DecodedImage.cs | 52 ++++++++- .../Generated/DecodedPointer.cs | 10 +- .../Generated/RawActiveStageOutput.cs | 2 +- .../{RawBytesArray.cs => RawBytesSlice.cs} | 14 +-- .../Generated/RawDatabase.cs | 24 ++++ .../Generated/RawDecodedImage.cs | 8 +- .../Generated/RawDecodedPointer.cs | 2 +- .../Generated/RawU32Slice.cs | 27 +++++ .../Devolutions.IronRdp/Generated/U32Slice.cs | 105 ++++++++++++++++++ ffi/src/graphics.rs | 6 +- ffi/src/input.rs | 13 +++ ffi/src/lib.rs | 3 +- ffi/src/pdu.rs | 2 - ffi/src/session/image.rs | 14 ++- ffi/src/session/mod.rs | 6 +- ffi/src/utils/mod.rs | 24 +++- 20 files changed, 369 insertions(+), 52 deletions(-) rename ffi/dotnet/Devolutions.IronRdp/Generated/{BytesArray.cs => BytesSlice.cs} (77%) create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/Database.cs rename ffi/dotnet/Devolutions.IronRdp/Generated/{RawBytesArray.cs => RawBytesSlice.cs} (59%) create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawDatabase.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawU32Slice.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/U32Slice.cs create mode 100644 ffi/src/input.rs diff --git a/ffi/Cargo.toml b/ffi/Cargo.toml index 2604117bb..26d5ae8a0 100644 --- a/ffi/Cargo.toml +++ b/ffi/Cargo.toml @@ -19,7 +19,7 @@ doctest = false [dependencies] diplomat = "0.7.0" diplomat-runtime = "0.7.0" -ironrdp = { workspace = true, features = ["connector", "dvc", "svc","rdpdr","rdpsnd","graphics"] } +ironrdp = { workspace = true, features = ["connector", "dvc", "svc","rdpdr","rdpsnd","graphics","input"] } sspi = { workspace = true, features = ["network_client"] } thiserror.workspace = true diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStageOutput.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStageOutput.cs index 1f195ca92..79390a827 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStageOutput.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStageOutput.cs @@ -47,7 +47,7 @@ public Position? PointerPosition } } - public BytesArray? ResponseFrame + public BytesSlice? ResponseFrame { get { @@ -102,9 +102,9 @@ public ActiveStageOutputType GetType() } /// - /// A BytesArray allocated on Rust side. + /// A BytesSlice allocated on Rust side. /// - public BytesArray? GetResponseFrame() + public BytesSlice? GetResponseFrame() { unsafe { @@ -112,12 +112,12 @@ public ActiveStageOutputType GetType() { throw new ObjectDisposedException("ActiveStageOutput"); } - Raw.BytesArray* retVal = Raw.ActiveStageOutput.GetResponseFrame(_inner); + Raw.BytesSlice* retVal = Raw.ActiveStageOutput.GetResponseFrame(_inner); if (retVal == null) { return null; } - return new BytesArray(retVal); + return new BytesSlice(retVal); } } diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/BytesArray.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/BytesSlice.cs similarity index 77% rename from ffi/dotnet/Devolutions.IronRdp/Generated/BytesArray.cs rename to ffi/dotnet/Devolutions.IronRdp/Generated/BytesSlice.cs index 2a342e2d2..a3f27f5af 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/BytesArray.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/BytesSlice.cs @@ -11,9 +11,9 @@ namespace Devolutions.IronRdp; #nullable enable -public partial class BytesArray: IDisposable +public partial class BytesSlice: IDisposable { - private unsafe Raw.BytesArray* _inner; + private unsafe Raw.BytesSlice* _inner; public nuint Size { @@ -24,7 +24,7 @@ public nuint Size } /// - /// Creates a managed BytesArray from a raw handle. + /// Creates a managed BytesSlice from a raw handle. /// /// /// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free). @@ -32,7 +32,7 @@ public nuint Size /// This constructor assumes the raw struct is allocated on Rust side. /// If implemented, the custom Drop implementation on Rust side WILL run on destruction. /// - public unsafe BytesArray(Raw.BytesArray* handle) + public unsafe BytesSlice(Raw.BytesSlice* handle) { _inner = handle; } @@ -43,9 +43,9 @@ public nuint GetSize() { if (_inner == null) { - throw new ObjectDisposedException("BytesArray"); + throw new ObjectDisposedException("BytesSlice"); } - nuint retVal = Raw.BytesArray.GetSize(_inner); + nuint retVal = Raw.BytesSlice.GetSize(_inner); return retVal; } } @@ -57,12 +57,12 @@ public void Fill(byte[] buffer) { if (_inner == null) { - throw new ObjectDisposedException("BytesArray"); + throw new ObjectDisposedException("BytesSlice"); } nuint bufferLength = (nuint)buffer.Length; fixed (byte* bufferPtr = buffer) { - Raw.UtilsFfiResultVoidBoxIronRdpError result = Raw.BytesArray.Fill(_inner, bufferPtr, bufferLength); + Raw.UtilsFfiResultVoidBoxIronRdpError result = Raw.BytesSlice.Fill(_inner, bufferPtr, bufferLength); if (!result.isOk) { throw new IronRdpException(new IronRdpError(result.Err)); @@ -74,7 +74,7 @@ public void Fill(byte[] buffer) /// /// Returns the underlying raw handle. /// - public unsafe Raw.BytesArray* AsFFI() + public unsafe Raw.BytesSlice* AsFFI() { return _inner; } @@ -91,14 +91,14 @@ public void Dispose() return; } - Raw.BytesArray.Destroy(_inner); + Raw.BytesSlice.Destroy(_inner); _inner = null; GC.SuppressFinalize(this); } } - ~BytesArray() + ~BytesSlice() { Dispose(); } diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/Database.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/Database.cs new file mode 100644 index 000000000..d3e15374a --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/Database.cs @@ -0,0 +1,75 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp; + +#nullable enable + +public partial class Database: IDisposable +{ + private unsafe Raw.Database* _inner; + + /// + /// Creates a managed Database from a raw handle. + /// + /// + /// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free). + ///
+ /// This constructor assumes the raw struct is allocated on Rust side. + /// If implemented, the custom Drop implementation on Rust side WILL run on destruction. + ///
+ public unsafe Database(Raw.Database* handle) + { + _inner = handle; + } + + /// + /// A Database allocated on Rust side. + /// + public static Database New() + { + unsafe + { + Raw.Database* retVal = Raw.Database.New(); + return new Database(retVal); + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.Database* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.Database.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~Database() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/DecodedImage.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/DecodedImage.cs index c3a06e36c..e8e409911 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/DecodedImage.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/DecodedImage.cs @@ -15,7 +15,7 @@ public partial class DecodedImage: IDisposable { private unsafe Raw.DecodedImage* _inner; - public BytesArray Data + public BytesSlice Data { get { @@ -23,6 +23,22 @@ public BytesArray Data } } + public ushort Height + { + get + { + return GetHeight(); + } + } + + public ushort Width + { + get + { + return GetWidth(); + } + } + /// /// Creates a managed DecodedImage from a raw handle. /// @@ -38,9 +54,35 @@ public unsafe DecodedImage(Raw.DecodedImage* handle) } /// - /// A BytesArray allocated on Rust side. + /// A BytesSlice allocated on Rust side. /// - public BytesArray GetData() + public BytesSlice GetData() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("DecodedImage"); + } + Raw.BytesSlice* retVal = Raw.DecodedImage.GetData(_inner); + return new BytesSlice(retVal); + } + } + + public ushort GetWidth() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("DecodedImage"); + } + ushort retVal = Raw.DecodedImage.GetWidth(_inner); + return retVal; + } + } + + public ushort GetHeight() { unsafe { @@ -48,8 +90,8 @@ public BytesArray GetData() { throw new ObjectDisposedException("DecodedImage"); } - Raw.BytesArray* retVal = Raw.DecodedImage.GetData(_inner); - return new BytesArray(retVal); + ushort retVal = Raw.DecodedImage.GetHeight(_inner); + return retVal; } } diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/DecodedPointer.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/DecodedPointer.cs index 3b0aa90c0..a967b6060 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/DecodedPointer.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/DecodedPointer.cs @@ -15,7 +15,7 @@ public partial class DecodedPointer: IDisposable { private unsafe Raw.DecodedPointer* _inner; - public BytesArray Data + public BytesSlice Data { get { @@ -122,9 +122,9 @@ public ushort GetHotspotY() } /// - /// A BytesArray allocated on Rust side. + /// A BytesSlice allocated on Rust side. /// - public BytesArray GetData() + public BytesSlice GetData() { unsafe { @@ -132,8 +132,8 @@ public BytesArray GetData() { throw new ObjectDisposedException("DecodedPointer"); } - Raw.BytesArray* retVal = Raw.DecodedPointer.GetData(_inner); - return new BytesArray(retVal); + Raw.BytesSlice* retVal = Raw.DecodedPointer.GetData(_inner); + return new BytesSlice(retVal); } } diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStageOutput.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStageOutput.cs index 912422222..02a6d42e0 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStageOutput.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStageOutput.cs @@ -20,7 +20,7 @@ public partial struct ActiveStageOutput public static unsafe extern ActiveStageOutputType GetType(ActiveStageOutput* self); [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStageOutput_get_response_frame", ExactSpelling = true)] - public static unsafe extern BytesArray* GetResponseFrame(ActiveStageOutput* self); + public static unsafe extern BytesSlice* GetResponseFrame(ActiveStageOutput* self); [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStageOutput_get_graphics_update", ExactSpelling = true)] public static unsafe extern InclusiveRectangle* GetGraphicsUpdate(ActiveStageOutput* self); diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawBytesArray.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawBytesSlice.cs similarity index 59% rename from ffi/dotnet/Devolutions.IronRdp/Generated/RawBytesArray.cs rename to ffi/dotnet/Devolutions.IronRdp/Generated/RawBytesSlice.cs index dd2955500..3d7e6f8ca 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/RawBytesArray.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawBytesSlice.cs @@ -12,16 +12,16 @@ namespace Devolutions.IronRdp.Raw; #nullable enable [StructLayout(LayoutKind.Sequential)] -public partial struct BytesArray +public partial struct BytesSlice { private const string NativeLib = "DevolutionsIronRdp"; - [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "BytesArray_get_size", ExactSpelling = true)] - public static unsafe extern nuint GetSize(BytesArray* self); + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "BytesSlice_get_size", ExactSpelling = true)] + public static unsafe extern nuint GetSize(BytesSlice* self); - [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "BytesArray_fill", ExactSpelling = true)] - public static unsafe extern UtilsFfiResultVoidBoxIronRdpError Fill(BytesArray* self, byte* buffer, nuint bufferSz); + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "BytesSlice_fill", ExactSpelling = true)] + public static unsafe extern UtilsFfiResultVoidBoxIronRdpError Fill(BytesSlice* self, byte* buffer, nuint bufferSz); - [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "BytesArray_destroy", ExactSpelling = true)] - public static unsafe extern void Destroy(BytesArray* self); + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "BytesSlice_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(BytesSlice* self); } diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawDatabase.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawDatabase.cs new file mode 100644 index 000000000..2403c70b5 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawDatabase.cs @@ -0,0 +1,24 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct Database +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Database_new", ExactSpelling = true)] + public static unsafe extern Database* New(); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Database_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(Database* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawDecodedImage.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawDecodedImage.cs index bc6e0e8f7..a07a74189 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/RawDecodedImage.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawDecodedImage.cs @@ -17,7 +17,13 @@ public partial struct DecodedImage private const string NativeLib = "DevolutionsIronRdp"; [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DecodedImage_get_data", ExactSpelling = true)] - public static unsafe extern BytesArray* GetData(DecodedImage* self); + public static unsafe extern BytesSlice* GetData(DecodedImage* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DecodedImage_get_width", ExactSpelling = true)] + public static unsafe extern ushort GetWidth(DecodedImage* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DecodedImage_get_height", ExactSpelling = true)] + public static unsafe extern ushort GetHeight(DecodedImage* self); [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DecodedImage_destroy", ExactSpelling = true)] public static unsafe extern void Destroy(DecodedImage* self); diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawDecodedPointer.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawDecodedPointer.cs index fc7f0485e..ba4de8bad 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/RawDecodedPointer.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawDecodedPointer.cs @@ -29,7 +29,7 @@ public partial struct DecodedPointer public static unsafe extern ushort GetHotspotY(DecodedPointer* self); [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DecodedPointer_get_data", ExactSpelling = true)] - public static unsafe extern BytesArray* GetData(DecodedPointer* self); + public static unsafe extern BytesSlice* GetData(DecodedPointer* self); [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DecodedPointer_destroy", ExactSpelling = true)] public static unsafe extern void Destroy(DecodedPointer* self); diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawU32Slice.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawU32Slice.cs new file mode 100644 index 000000000..bdf2dca80 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawU32Slice.cs @@ -0,0 +1,27 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct U32Slice +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "U32Slice_get_size", ExactSpelling = true)] + public static unsafe extern nuint GetSize(U32Slice* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "U32Slice_fill", ExactSpelling = true)] + public static unsafe extern UtilsFfiResultVoidBoxIronRdpError Fill(U32Slice* self, uint* buffer, nuint bufferSz); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "U32Slice_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(U32Slice* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/U32Slice.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/U32Slice.cs new file mode 100644 index 000000000..e552913cf --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/U32Slice.cs @@ -0,0 +1,105 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp; + +#nullable enable + +public partial class U32Slice: IDisposable +{ + private unsafe Raw.U32Slice* _inner; + + public nuint Size + { + get + { + return GetSize(); + } + } + + /// + /// Creates a managed U32Slice from a raw handle. + /// + /// + /// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free). + ///
+ /// This constructor assumes the raw struct is allocated on Rust side. + /// If implemented, the custom Drop implementation on Rust side WILL run on destruction. + ///
+ public unsafe U32Slice(Raw.U32Slice* handle) + { + _inner = handle; + } + + public nuint GetSize() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("U32Slice"); + } + nuint retVal = Raw.U32Slice.GetSize(_inner); + return retVal; + } + } + + /// + public void Fill(uint[] buffer) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("U32Slice"); + } + nuint bufferLength = (nuint)buffer.Length; + fixed (uint* bufferPtr = buffer) + { + Raw.UtilsFfiResultVoidBoxIronRdpError result = Raw.U32Slice.Fill(_inner, bufferPtr, bufferLength); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + } + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.U32Slice* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.U32Slice.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~U32Slice() + { + Dispose(); + } +} diff --git a/ffi/src/graphics.rs b/ffi/src/graphics.rs index 22c9e1e7c..ae1016f6c 100644 --- a/ffi/src/graphics.rs +++ b/ffi/src/graphics.rs @@ -3,7 +3,7 @@ pub mod ffi { use std::rc::Rc; - use crate::utils::ffi::BytesArray; + use crate::utils::ffi::BytesSlice; #[diplomat::opaque] pub struct DecodedPointer(pub Rc); @@ -25,8 +25,8 @@ pub mod ffi { self.0.hotspot_y } - pub fn get_data<'a>(&'a self) -> Box> { - Box::new(BytesArray(&self.0.bitmap_data)) + pub fn get_data<'a>(&'a self) -> Box> { + Box::new(BytesSlice(&self.0.bitmap_data)) } } } \ No newline at end of file diff --git a/ffi/src/input.rs b/ffi/src/input.rs new file mode 100644 index 000000000..df65f2a69 --- /dev/null +++ b/ffi/src/input.rs @@ -0,0 +1,13 @@ + +#[diplomat::bridge] +pub mod ffi { + #[diplomat::opaque] + pub struct Database(pub ironrdp::input::Database); + + impl Database { + pub fn new() -> Box { + Box::new(Database(ironrdp::input::Database::new())) + } + + } +} \ No newline at end of file diff --git a/ffi/src/lib.rs b/ffi/src/lib.rs index 3b4c1af1b..9ab8db7a0 100644 --- a/ffi/src/lib.rs +++ b/ffi/src/lib.rs @@ -8,4 +8,5 @@ pub mod pdu; pub mod svc; pub mod utils; pub mod session; -pub mod graphics; \ No newline at end of file +pub mod graphics; +pub mod input; \ No newline at end of file diff --git a/ffi/src/pdu.rs b/ffi/src/pdu.rs index 776755410..2ad6309c7 100644 --- a/ffi/src/pdu.rs +++ b/ffi/src/pdu.rs @@ -1,8 +1,6 @@ #[diplomat::bridge] pub mod ffi { - use ironrdp::pdu::Pdu; - use crate::error::ffi::IronRdpError; #[diplomat::opaque] diff --git a/ffi/src/session/image.rs b/ffi/src/session/image.rs index 1120c8285..6b700fc34 100644 --- a/ffi/src/session/image.rs +++ b/ffi/src/session/image.rs @@ -1,6 +1,6 @@ #[diplomat::bridge] pub mod ffi { - use crate::utils::ffi::BytesArray; + use crate::utils::ffi::BytesSlice; #[diplomat::opaque] @@ -8,8 +8,16 @@ pub mod ffi { impl<'a> DecodedImage<'a> { // The bytes array lives as long as the DecodedImage - pub fn get_data(&'a self) -> Box>{ - Box::new(BytesArray(self.0.data())) + pub fn get_data(&'a self) -> Box>{ + Box::new(BytesSlice(self.0.data())) + } + + pub fn get_width(&self) -> u16 { + self.0.width() + } + + pub fn get_height(&self) -> u16 { + self.0.height() } } } \ No newline at end of file diff --git a/ffi/src/session/mod.rs b/ffi/src/session/mod.rs index 368a86d94..1a83742a4 100644 --- a/ffi/src/session/mod.rs +++ b/ffi/src/session/mod.rs @@ -4,7 +4,7 @@ pub mod image; pub mod ffi { use crate::{ - connector::ffi::ConnectionActivationSequence, error::ffi::IronRdpError, graphics::ffi::DecodedPointer, pdu::ffi::{Action, InclusiveRectangle}, utils::ffi::{BytesArray, Position} + connector::ffi::ConnectionActivationSequence, error::ffi::IronRdpError, graphics::ffi::DecodedPointer, pdu::ffi::{Action, InclusiveRectangle}, utils::ffi::{BytesSlice, Position} }; use super::image::ffi::DecodedImage; @@ -65,9 +65,9 @@ pub mod ffi { } } - pub fn get_response_frame<'a>(&'a self) -> Option>> { + pub fn get_response_frame<'a>(&'a self) -> Option>> { match &self.0 { - ironrdp::session::ActiveStageOutput::ResponseFrame(frame) => Some(Box::new(BytesArray(frame))), + ironrdp::session::ActiveStageOutput::ResponseFrame(frame) => Some(Box::new(BytesSlice(frame))), _ => None, } } diff --git a/ffi/src/utils/mod.rs b/ffi/src/utils/mod.rs index 6694893a5..2e872f12a 100644 --- a/ffi/src/utils/mod.rs +++ b/ffi/src/utils/mod.rs @@ -29,9 +29,9 @@ pub mod ffi { } #[diplomat::opaque] - pub struct BytesArray<'a>(pub &'a [u8]); + pub struct BytesSlice<'a>(pub &'a [u8]); - impl<'a> BytesArray<'a> { + impl<'a> BytesSlice<'a> { pub fn get_size(&'a self) -> usize { self.0.len() } @@ -43,7 +43,24 @@ pub mod ffi { buffer.copy_from_slice(&self.0); Ok(()) } - + + } + + #[diplomat::opaque] + pub struct U32Slice<'a>(pub &'a [u32]); + + impl<'a> U32Slice<'a> { + pub fn get_size(&'a self) -> usize { + self.0.len() + } + + pub fn fill(&'a self, buffer: &'a mut [u32]) -> Result<(), Box> { + if buffer.len() < self.0.len() { + return Err("Buffer is too small".into()); + } + buffer.copy_from_slice(&self.0); + Ok(()) + } } #[diplomat::opaque] @@ -74,4 +91,5 @@ pub mod ffi { self.0.ok_or_else(|| "Value is None".into()) } } + } From 09194548111ca579c54eaeb91a04247ce4fed92b Mon Sep 17 00:00:00 2001 From: irving ou Date: Fri, 5 Apr 2024 16:45:50 -0400 Subject: [PATCH 06/18] WIP:add byte list --- .../Devolutions.IronRdp/src/ByteList.cs | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 ffi/dotnet/Devolutions.IronRdp/src/ByteList.cs diff --git a/ffi/dotnet/Devolutions.IronRdp/src/ByteList.cs b/ffi/dotnet/Devolutions.IronRdp/src/ByteList.cs new file mode 100644 index 000000000..8b246b5bb --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/src/ByteList.cs @@ -0,0 +1,57 @@ + +public class ByteList { + + private inner: byte[] + private occupied: int + + public ByteList(int capacity) { + this.capacity = capacity + this.inner = new byte[capacity] + } + + public ByteList(int capacity, byte[] bytes) { + this.capacity = capacity + this.inner = new byte[capacity] + this.AddRange(bytes) + } + + public byte[] Peek() { + return this.inner + } + + public void AddRange(byte[] bytes) { + while (bytes.Length > this.capacity) { + this.Grow() + } + Array.Copy(bytes, 0, this.inner, 0, bytes.Length) + } + + /// + /// Split the ByteList into two parts. The first part will returned and removed from the ByteList. The second part will remain in the ByteList. + /// The Returned Part will be contain [0, at) bytes from the ByteList. and the ByteList will contain [at, occupied) bytes. + /// + /// The size of the byte array to split. + /// A new byte array containing the split bytes. + public ByteList SplitTo(int at) { + if (at > this.occupied) { + throw new Exception("Not enough bytes to split") + } + + var res = new byte[at] + Array.Copy(this.inner, 0, res, 0, at) + Array.Copy(this.inner, at, this.inner, 0, this.occupied - at) + this.occupied -= at + return ByteList(at, res) + } + + private void Grow() { + if (this.capacity == 0) { + this.capacity = 1 + } else { + this.capacity *= 2 + } + + var newInner = new byte[this.capacity] + Array.Copy(this.inner, 0, newInner, 0, this.occupied) + } +} \ No newline at end of file From e833dcec5e9179fb61c8457faa42106b4d7fe164 Mon Sep 17 00:00:00 2001 From: irving ou Date: Fri, 5 Apr 2024 16:46:41 -0400 Subject: [PATCH 07/18] WIP:add byte list --- .../Devolutions.IronRdp/src/ByteList.cs | 60 +++++++++---------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/ffi/dotnet/Devolutions.IronRdp/src/ByteList.cs b/ffi/dotnet/Devolutions.IronRdp/src/ByteList.cs index 8b246b5bb..abafcf6eb 100644 --- a/ffi/dotnet/Devolutions.IronRdp/src/ByteList.cs +++ b/ffi/dotnet/Devolutions.IronRdp/src/ByteList.cs @@ -1,57 +1,55 @@ - public class ByteList { - private inner: byte[] - private occupied: int + private byte[] inner; + private int occupied = 0; + private int capacity; public ByteList(int capacity) { - this.capacity = capacity - this.inner = new byte[capacity] + this.capacity = capacity; + this.inner = new byte[capacity]; } public ByteList(int capacity, byte[] bytes) { - this.capacity = capacity - this.inner = new byte[capacity] - this.AddRange(bytes) + this.capacity = capacity; + this.inner = new byte[capacity]; + this.AddRange(bytes); } public byte[] Peek() { - return this.inner + return java.util.Arrays.copyOf(inner, occupied); } public void AddRange(byte[] bytes) { - while (bytes.Length > this.capacity) { - this.Grow() + while (bytes.length + occupied > capacity) { + this.Grow(); } - Array.Copy(bytes, 0, this.inner, 0, bytes.Length) + System.arraycopy(bytes, 0, this.inner, occupied, bytes.length); + occupied += bytes.length; } - /// - /// Split the ByteList into two parts. The first part will returned and removed from the ByteList. The second part will remain in the ByteList. - /// The Returned Part will be contain [0, at) bytes from the ByteList. and the ByteList will contain [at, occupied) bytes. - /// - /// The size of the byte array to split. - /// A new byte array containing the split bytes. public ByteList SplitTo(int at) { - if (at > this.occupied) { - throw new Exception("Not enough bytes to split") + if (at > occupied) { + throw new IllegalArgumentException("Not enough bytes to split"); } - var res = new byte[at] - Array.Copy(this.inner, 0, res, 0, at) - Array.Copy(this.inner, at, this.inner, 0, this.occupied - at) - this.occupied -= at - return ByteList(at, res) + byte[] res = new byte[at]; + System.arraycopy(this.inner, 0, res, 0, at); + System.arraycopy(this.inner, at, this.inner, 0, occupied - at); + occupied -= at; + + ByteList resultByteList = new ByteList(capacity, res); + return resultByteList; } private void Grow() { - if (this.capacity == 0) { - this.capacity = 1 + if (capacity == 0) { + capacity = 1; } else { - this.capacity *= 2 + capacity *= 2; } - var newInner = new byte[this.capacity] - Array.Copy(this.inner, 0, newInner, 0, this.occupied) + byte[] newInner = new byte[capacity]; + System.arraycopy(inner, 0, newInner, 0, occupied); + inner = newInner; } -} \ No newline at end of file +} From 14a52664cf31b9e3c4f77e776741b71c1068517f Mon Sep 17 00:00:00 2001 From: irving ou Date: Sun, 7 Apr 2024 12:27:45 -0400 Subject: [PATCH 08/18] WIP:remove byte list --- .../Devolutions.IronRdp/src/ByteList.cs | 55 ------------------- 1 file changed, 55 deletions(-) delete mode 100644 ffi/dotnet/Devolutions.IronRdp/src/ByteList.cs diff --git a/ffi/dotnet/Devolutions.IronRdp/src/ByteList.cs b/ffi/dotnet/Devolutions.IronRdp/src/ByteList.cs deleted file mode 100644 index abafcf6eb..000000000 --- a/ffi/dotnet/Devolutions.IronRdp/src/ByteList.cs +++ /dev/null @@ -1,55 +0,0 @@ -public class ByteList { - - private byte[] inner; - private int occupied = 0; - private int capacity; - - public ByteList(int capacity) { - this.capacity = capacity; - this.inner = new byte[capacity]; - } - - public ByteList(int capacity, byte[] bytes) { - this.capacity = capacity; - this.inner = new byte[capacity]; - this.AddRange(bytes); - } - - public byte[] Peek() { - return java.util.Arrays.copyOf(inner, occupied); - } - - public void AddRange(byte[] bytes) { - while (bytes.length + occupied > capacity) { - this.Grow(); - } - System.arraycopy(bytes, 0, this.inner, occupied, bytes.length); - occupied += bytes.length; - } - - public ByteList SplitTo(int at) { - if (at > occupied) { - throw new IllegalArgumentException("Not enough bytes to split"); - } - - byte[] res = new byte[at]; - System.arraycopy(this.inner, 0, res, 0, at); - System.arraycopy(this.inner, at, this.inner, 0, occupied - at); - occupied -= at; - - ByteList resultByteList = new ByteList(capacity, res); - return resultByteList; - } - - private void Grow() { - if (capacity == 0) { - capacity = 1; - } else { - capacity *= 2; - } - - byte[] newInner = new byte[capacity]; - System.arraycopy(inner, 0, newInner, 0, occupied); - inner = newInner; - } -} From d91299fa3ef23d3afe973614404cb2a82431e53d Mon Sep 17 00:00:00 2001 From: irving ou Date: Sun, 7 Apr 2024 22:03:51 -0400 Subject: [PATCH 09/18] ARC-212-ScreenShot --- .../.gitignore | 3 +- .../Devolutions.IronRdp.ConnectExample.csproj | 5 + .../Program.cs | 315 +++++------------- .../Generated/ActiveStage.cs | 24 ++ .../Generated/ActiveStageOutputIterator.cs | 13 + .../Generated/ClientConnector.cs | 40 ++- .../Generated/ClientConnectorState.cs | 54 --- .../Generated/ConnectionResult.cs | 62 ++-- .../Generated/DecodedImage.cs | 14 + .../{State.cs => DynClientConnectorState.cs} | 26 +- .../Generated/IronRdpPdu.cs | 12 + .../Generated/PixelFormat.cs | 24 ++ .../Generated/RawActiveStage.cs | 3 + .../Generated/RawActiveStageOutputIterator.cs | 4 + .../Generated/RawClientConnector.cs | 7 +- .../Generated/RawClientConnectorState.cs | 6 - .../Generated/RawConnectionResult.cs | 15 +- ...tBoxClientConnectorStateBoxIronRdpError.cs | 46 +++ ...xDynClientConnectorStateBoxIronRdpError.cs | 46 +++ ...ctorResultFfiResultBoolBoxIronRdpError.cs} | 6 +- ...tFfiResultBoxDesktopSizeBoxIronRdpError.cs | 46 +++ ...ectorResultFfiResultU16BoxIronRdpError.cs} | 2 +- .../Generated/RawDecodedImage.cs | 3 + ...State.cs => RawDynClientConnectorState.cs} | 14 +- .../Generated/RawIronRdpPdu.cs | 3 + .../Generated/RawPixelFormat.cs | 24 ++ ...nFfiResultBoxActiveStageBoxIronRdpError.cs | 46 +++ .../Devolutions.IronRdp/src/Connection.cs | 237 +++++++++++++ .../Devolutions.IronRdp/src/Exceptions.cs | 18 + ffi/dotnet/Devolutions.IronRdp/src/Framed.cs | 19 ++ ffi/src/connector/mod.rs | 21 +- ffi/src/connector/result.rs | 55 ++- ffi/src/connector/state.rs | 101 +++--- ffi/src/graphics.rs | 5 +- ffi/src/input.rs | 4 +- ffi/src/lib.rs | 6 +- ffi/src/pdu.rs | 4 + ffi/src/session/image.rs | 29 +- ffi/src/session/mod.rs | 41 ++- ffi/src/utils/mod.rs | 10 +- 40 files changed, 960 insertions(+), 453 deletions(-) rename ffi/dotnet/Devolutions.IronRdp/Generated/{State.cs => DynClientConnectorState.cs} (73%) create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/PixelFormat.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoxClientConnectorStateBoxIronRdpError.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoxDynClientConnectorStateBoxIronRdpError.cs rename ffi/dotnet/Devolutions.IronRdp/Generated/{RawConnectorFfiResultBoxStateBoxIronRdpError.cs => RawConnectorResultFfiResultBoolBoxIronRdpError.cs} (85%) create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorResultFfiResultBoxDesktopSizeBoxIronRdpError.cs rename ffi/dotnet/Devolutions.IronRdp/Generated/{RawConnectorStateFfiResultU16BoxIronRdpError.cs => RawConnectorResultFfiResultU16BoxIronRdpError.cs} (92%) rename ffi/dotnet/Devolutions.IronRdp/Generated/{RawState.cs => RawDynClientConnectorState.cs} (55%) create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawPixelFormat.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxActiveStageBoxIronRdpError.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/src/Connection.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/src/Exceptions.cs diff --git a/ffi/dotnet/Devolutions.IronRdp.ConnectExample/.gitignore b/ffi/dotnet/Devolutions.IronRdp.ConnectExample/.gitignore index 501bb1289..12100f6a1 100644 --- a/ffi/dotnet/Devolutions.IronRdp.ConnectExample/.gitignore +++ b/ffi/dotnet/Devolutions.IronRdp.ConnectExample/.gitignore @@ -1,3 +1,4 @@ obj bin -.vs \ No newline at end of file +.vs +output.bmp \ No newline at end of file diff --git a/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Devolutions.IronRdp.ConnectExample.csproj b/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Devolutions.IronRdp.ConnectExample.csproj index 2e1eeb1b9..deef7a6dc 100644 --- a/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Devolutions.IronRdp.ConnectExample.csproj +++ b/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Devolutions.IronRdp.ConnectExample.csproj @@ -10,5 +10,10 @@ + + + + + diff --git a/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Program.cs b/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Program.cs index d09ee3625..e435557c4 100644 --- a/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Program.cs +++ b/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Program.cs @@ -1,6 +1,6 @@ -using System.Net; -using System.Net.Security; -using System.Net.Sockets; +using System.Drawing; +using System.Drawing.Imaging; +using Devolutions.IronRdp; namespace Devolutions.IronRdp.ConnectExample { @@ -10,9 +10,9 @@ static async Task Main(string[] args) { var arguments = ParseArguments(args); - if (arguments == null) + if (arguments == null) { - return; + return; } var serverName = arguments["--serverName"]; @@ -21,15 +21,95 @@ static async Task Main(string[] args) var domain = arguments["--domain"]; try { - await Connect(serverName, username, password, domain); + var (res, framed) = await Connection.Connect(serverName, username, password, domain, 1980, 1080); + var decodedImage = DecodedImage.New(PixelFormat.RgbA32, res.GetDesktopSize().GetWidth(), res.GetDesktopSize().GetHeight()); + var activeState = ActiveStage.New(res); + var keepLooping = true; + while (keepLooping) + { + var readPduTask = framed.ReadPdu(); + Action? action = null; + byte[]? payload = null; + if (readPduTask == await Task.WhenAny(readPduTask, Task.Delay(1000))) + { + var pduReadTask = await readPduTask; + action = pduReadTask.Item1; + payload = pduReadTask.Item2; + Console.WriteLine($"Action: {action}"); + } + else + { + Console.WriteLine("Timeout"); + keepLooping = false; + continue; + } + var outputIterator = activeState.Process(decodedImage, action, payload); + + while (!outputIterator.IsEmpty()) + { + var output = outputIterator.Next()!; // outputIterator.Next() is not null since outputIterator.IsEmpty() is false + Console.WriteLine($"Output type: {output.GetType()}"); + if (output.GetType() == ActiveStageOutputType.Terminate) + { + Console.WriteLine("Connection terminated."); + keepLooping = false; + } + + if (output.GetType() == ActiveStageOutputType.ResponseFrame) + { + var responseFrame = output.GetResponseFrame()!; + byte[] responseFrameBytes = new byte[responseFrame.GetSize()]; + responseFrame.Fill(responseFrameBytes); + await framed.Write(responseFrameBytes); + } + } + } + + saveImage(decodedImage, "output.png"); + } - catch (Exception e) + catch (Exception e) { Console.WriteLine($"An error occurred: {e.Message}"); } } - static Dictionary ParseArguments(string[] args) + private static void saveImage(DecodedImage decodedImage, string v) + { + int width = decodedImage.GetWidth(); + int height = decodedImage.GetHeight(); + var data = decodedImage.GetData(); + + var bytes = new byte[data.GetSize()]; + data.Fill(bytes); + for (int i = 0; i < bytes.Length; i += 4) + { + byte temp = bytes[i]; // Store the original Blue value + bytes[i] = bytes[i + 2]; // Move Red to Blue's position + bytes[i + 2] = temp; // Move original Blue to Red's position + // Green (bytes[i+1]) and Alpha (bytes[i+3]) remain unchanged + } + using (var bmp = new Bitmap(width, height)) + { + // Lock the bits of the bitmap. + var bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), + ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); + + // Get the address of the first line. + IntPtr ptr = bmpData.Scan0; + // Copy the RGBA values back to the bitmap + System.Runtime.InteropServices.Marshal.Copy(bytes, 0, ptr, bytes.Length); + // Unlock the bits. + bmp.UnlockBits(bmpData); + + // Save the bitmap to the specified output path + bmp.Save("./output.bmp", ImageFormat.Bmp); + } + + + } + + static Dictionary? ParseArguments(string[] args) { if (args.Length == 0 || Array.Exists(args, arg => arg == "--help")) { @@ -97,222 +177,5 @@ static void PrintHelp() Console.WriteLine(" --help Show this message and exit."); } - static async Task Connect(String servername, String username, String password, String domain) - { - Config config = buildConfig(servername, username, password, domain); - - var stream = await CreateTcpConnection(servername, 3389); - var framed = new Framed(stream); - - ClientConnector connector = ClientConnector.New(config); - - var ip = await Dns.GetHostAddressesAsync(servername); - if (ip.Length == 0) - { - throw new Exception("Could not resolve server address"); - } - - var socketAddrString = ip[0].ToString()+":3389"; - connector.WithServerAddr(socketAddrString); - - await connectBegin(framed, connector); - var (serverPublicKey, framedSsl) = await securityUpgrade(servername, framed, connector); - await ConnectFinalize(servername, connector, serverPublicKey, framedSsl); - } - - private static async Task<(byte[], Framed)> securityUpgrade(string servername, Framed framed, ClientConnector connector) - { - byte[] serverPublicKey; - Framed framedSsl; - var (streamRequireUpgrade, _) = framed.GetInner(); - var promise = new TaskCompletionSource(); - var sslStream = new SslStream(streamRequireUpgrade, false, (sender, certificate, chain, sslPolicyErrors) => - { - promise.SetResult(certificate!.GetPublicKey()); - return true; - }); - await sslStream.AuthenticateAsClientAsync(servername); - serverPublicKey = await promise.Task; - framedSsl = new Framed(sslStream); - connector.MarkSecurityUpgradeAsDone(); - - return (serverPublicKey, framedSsl); - } - - private static async Task connectBegin(Framed framed, ClientConnector connector) - { - var writeBuf = WriteBuf.New(); - while (!connector.ShouldPerformSecurityUpgrade()) - { - await SingleConnectStep(connector, writeBuf, framed); - } - } - - private static Config buildConfig(string servername, string username, string password, string domain) - { - ConfigBuilder configBuilder = ConfigBuilder.New(); - - configBuilder.WithUsernameAndPasswrord(username, password); - configBuilder.SetDomain(domain); - configBuilder.SetDesktopSize(800, 600); - configBuilder.SetClientName("IronRdp"); - configBuilder.SetClientDir("C:\\"); - configBuilder.SetPerformanceFlags(PerformanceFlags.NewDefault()); - - return configBuilder.Build(); - } - - private static async Task ConnectFinalize(string servername, ClientConnector connector, byte[] serverpubkey, Framed framedSsl) - { - var writeBuf2 = WriteBuf.New(); - if (connector.ShouldPerformCredssp()) - { - await PerformCredsspSteps(connector, servername, writeBuf2, framedSsl, serverpubkey); - } - while (!connector.State().IsTerminal()) - { - await SingleConnectStep(connector, writeBuf2, framedSsl); - } - } - - private static async Task PerformCredsspSteps(ClientConnector connector, string serverName, WriteBuf writeBuf, Framed framedSsl, byte[] serverpubkey) - { - var credsspSequenceInitResult = CredsspSequence.Init(connector, serverName, serverpubkey, null); - var credsspSequence = credsspSequenceInitResult.GetCredsspSequence(); - var tsRequest = credsspSequenceInitResult.GetTsRequest(); - TcpClient tcpClient = new TcpClient(); - while (true) - { - var generator = credsspSequence.ProcessTsRequest(tsRequest); - var clientState = await ResolveGenerator(generator, tcpClient); - writeBuf.Clear(); - var written = credsspSequence.HandleProcessResult(clientState, writeBuf); - - if (written.GetSize().IsSome()) - { - var actualSize = (int)written.GetSize().Get(); - var response = new byte[actualSize]; - writeBuf.ReadIntoBuf(response); - await framedSsl.Write(response); - } - - var pduHint = credsspSequence.NextPduHint()!; - if (pduHint == null) - { - break; - } - - var pdu = await framedSsl.ReadByHint(pduHint); - var decoded = credsspSequence.DecodeServerMessage(pdu); - - if (null == decoded) - { - break; - } - - tsRequest = decoded; - } - } - - private static async Task ResolveGenerator(CredsspProcessGenerator generator, TcpClient tcpClient) - { - var state = generator.Start(); - NetworkStream stream = null; - while (true) - { - if (state.IsSuspended()) - { - var request = state.GetNetworkRequestIfSuspended()!; - var protocol = request.GetProtocol(); - var url = request.GetUrl(); - var data = request.GetData(); - if (null == stream) - { - url = url.Replace("tcp://", ""); - var split = url.Split(":"); - await tcpClient.ConnectAsync(split[0], int.Parse(split[1])); - stream = tcpClient.GetStream(); - - } - if (protocol == NetworkRequestProtocol.Tcp) - { - stream.Write(Utils.Vecu8ToByte(data)); - var readBuf = new byte[8096]; - var readlen = await stream.ReadAsync(readBuf, 0, readBuf.Length); - var actuallyRead = new byte[readlen]; - Array.Copy(readBuf, actuallyRead, readlen); - state = generator.Resume(actuallyRead); - } - else - { - throw new Exception("Unimplemented protocol"); - } - } - else - { - var client_state = state.GetClientStateIfCompleted(); - return client_state; - } - } - } - - static async Task SingleConnectStep(ClientConnector connector, WriteBuf buf, Framed framed) - where T : Stream - { - buf.Clear(); - - var pduHint = connector.NextPduHint(); - Written written; - if (pduHint != null) - { - byte[] pdu = await framed.ReadByHint(pduHint); - written = connector.Step(pdu, buf); - } - else - { - written = connector.StepNoInput(buf); - } - - if (written.GetWrittenType() == WrittenType.Nothing) - { - return; - } - - // will throw if size is not set - var size = written.GetSize().Get(); - - var response = new byte[size]; - buf.ReadIntoBuf(response); - - await framed.Write(response); - } - - static async Task CreateTcpConnection(String servername, int port) - { - IPHostEntry ipHostInfo = await Dns.GetHostEntryAsync(servername); - IPAddress ipAddress = ipHostInfo.AddressList[0]; - IPEndPoint ipEndPoint = new(ipAddress, port); - - TcpClient client = new TcpClient(); - - await client.ConnectAsync(ipEndPoint); - NetworkStream stream = client.GetStream(); - - return stream; - } - } - - public static class Utils - { - public static byte[] Vecu8ToByte(VecU8 vecU8) - { - var len = vecU8.GetSize(); - byte[] buffer = new byte[len]; - vecU8.Fill(buffer); - return buffer; - } - } -} - - +} \ No newline at end of file diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStage.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStage.cs index 7770d1b62..ed32efa1c 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStage.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStage.cs @@ -29,6 +29,30 @@ public unsafe ActiveStage(Raw.ActiveStage* handle) _inner = handle; } + /// + /// + /// A ActiveStage allocated on Rust side. + /// + public static ActiveStage New(ConnectionResult connectionResult) + { + unsafe + { + Raw.ConnectionResult* connectionResultRaw; + connectionResultRaw = connectionResult.AsFFI(); + if (connectionResultRaw == null) + { + throw new ObjectDisposedException("ConnectionResult"); + } + Raw.SessionFfiResultBoxActiveStageBoxIronRdpError result = Raw.ActiveStage.New(connectionResultRaw); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.ActiveStage* retVal = result.Ok; + return new ActiveStage(retVal); + } + } + /// /// /// A ActiveStageOutputIterator allocated on Rust side. diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStageOutputIterator.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStageOutputIterator.cs index b8f02de2b..b36097c6e 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStageOutputIterator.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStageOutputIterator.cs @@ -42,6 +42,19 @@ public nuint Len() } } + public bool IsEmpty() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ActiveStageOutputIterator"); + } + bool retVal = Raw.ActiveStageOutputIterator.IsEmpty(_inner); + return retVal; + } + } + /// /// A ActiveStageOutput allocated on Rust side. /// diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/ClientConnector.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/ClientConnector.cs index b87c0fce1..dc594ae54 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/ClientConnector.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/ClientConnector.cs @@ -15,6 +15,14 @@ public partial class ClientConnector: IDisposable { private unsafe Raw.ClientConnector* _inner; + public DynClientConnectorState DynState + { + get + { + return GetDynState(); + } + } + /// /// Creates a managed ClientConnector from a raw handle. /// @@ -277,9 +285,31 @@ public PduHint NextPduHint() /// /// - /// A State allocated on Rust side. + /// A DynClientConnectorState allocated on Rust side. + /// + public DynClientConnectorState GetDynState() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ClientConnector"); + } + Raw.ConnectorFfiResultBoxDynClientConnectorStateBoxIronRdpError result = Raw.ClientConnector.GetDynState(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.DynClientConnectorState* retVal = result.Ok; + return new DynClientConnectorState(retVal); + } + } + + /// + /// + /// A ClientConnectorState allocated on Rust side. /// - public State State() + public ClientConnectorState ConsumeSelfAndGetState() { unsafe { @@ -287,13 +317,13 @@ public State State() { throw new ObjectDisposedException("ClientConnector"); } - Raw.ConnectorFfiResultBoxStateBoxIronRdpError result = Raw.ClientConnector.State(_inner); + Raw.ConnectorFfiResultBoxClientConnectorStateBoxIronRdpError result = Raw.ClientConnector.ConsumeSelfAndGetState(_inner); if (!result.isOk) { throw new IronRdpException(new IronRdpError(result.Err)); } - Raw.State* retVal = result.Ok; - return new State(retVal); + Raw.ClientConnectorState* retVal = result.Ok; + return new ClientConnectorState(retVal); } } diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/ClientConnectorState.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/ClientConnectorState.cs index dbe82b0c2..1b4b692df 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/ClientConnectorState.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/ClientConnectorState.cs @@ -31,14 +31,6 @@ public ConnectInitial BasicSettingsExchangeWaitResponseConnectInitial } } - public ushort ChannelConnectionIoChannelId - { - get - { - return GetChannelConnectionIoChannelId(); - } - } - public ConnectionResult ConnectedResult { get @@ -71,14 +63,6 @@ public SecurityProtocol EnhancedSecurityUpgradeSelectedProtocol } } - public ushort SecureSettingsExchangeIoChannelId - { - get - { - return GetSecureSettingsExchangeIoChannelId(); - } - } - public ClientConnectorStateType Type { get @@ -233,44 +217,6 @@ public ConnectInitial GetBasicSettingsExchangeWaitResponseConnectInitial() } } - /// - public ushort GetChannelConnectionIoChannelId() - { - unsafe - { - if (_inner == null) - { - throw new ObjectDisposedException("ClientConnectorState"); - } - Raw.ConnectorStateFfiResultU16BoxIronRdpError result = Raw.ClientConnectorState.GetChannelConnectionIoChannelId(_inner); - if (!result.isOk) - { - throw new IronRdpException(new IronRdpError(result.Err)); - } - ushort retVal = result.Ok; - return retVal; - } - } - - /// - public ushort GetSecureSettingsExchangeIoChannelId() - { - unsafe - { - if (_inner == null) - { - throw new ObjectDisposedException("ClientConnectorState"); - } - Raw.ConnectorStateFfiResultU16BoxIronRdpError result = Raw.ClientConnectorState.GetSecureSettingsExchangeIoChannelId(_inner); - if (!result.isOk) - { - throw new IronRdpException(new IronRdpError(result.Err)); - } - ushort retVal = result.Ok; - return retVal; - } - } - /// /// /// A ConnectionResult allocated on Rust side. diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/ConnectionResult.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/ConnectionResult.cs index d1d84d4b8..ce5ea459b 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/ConnectionResult.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/ConnectionResult.cs @@ -47,14 +47,6 @@ public bool PointerSoftwareRendering } } - public StaticChannelSet StaticChannels - { - get - { - return GetStaticChannels(); - } - } - public ushort UserChannelId { get @@ -77,6 +69,7 @@ public unsafe ConnectionResult(Raw.ConnectionResult* handle) _inner = handle; } + /// public ushort GetIoChannelId() { unsafe @@ -85,11 +78,17 @@ public ushort GetIoChannelId() { throw new ObjectDisposedException("ConnectionResult"); } - ushort retVal = Raw.ConnectionResult.GetIoChannelId(_inner); + Raw.ConnectorResultFfiResultU16BoxIronRdpError result = Raw.ConnectionResult.GetIoChannelId(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + ushort retVal = result.Ok; return retVal; } } + /// public ushort GetUserChannelId() { unsafe @@ -98,27 +97,17 @@ public ushort GetUserChannelId() { throw new ObjectDisposedException("ConnectionResult"); } - ushort retVal = Raw.ConnectionResult.GetUserChannelId(_inner); - return retVal; - } - } - - /// - /// A StaticChannelSet allocated on Rust side. - /// - public StaticChannelSet GetStaticChannels() - { - unsafe - { - if (_inner == null) + Raw.ConnectorResultFfiResultU16BoxIronRdpError result = Raw.ConnectionResult.GetUserChannelId(_inner); + if (!result.isOk) { - throw new ObjectDisposedException("ConnectionResult"); + throw new IronRdpException(new IronRdpError(result.Err)); } - Raw.StaticChannelSet* retVal = Raw.ConnectionResult.GetStaticChannels(_inner); - return new StaticChannelSet(retVal); + ushort retVal = result.Ok; + return retVal; } } + /// /// /// A DesktopSize allocated on Rust side. /// @@ -130,11 +119,17 @@ public DesktopSize GetDesktopSize() { throw new ObjectDisposedException("ConnectionResult"); } - Raw.DesktopSize* retVal = Raw.ConnectionResult.GetDesktopSize(_inner); + Raw.ConnectorResultFfiResultBoxDesktopSizeBoxIronRdpError result = Raw.ConnectionResult.GetDesktopSize(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.DesktopSize* retVal = result.Ok; return new DesktopSize(retVal); } } + /// public bool GetNoServerPointer() { unsafe @@ -143,11 +138,17 @@ public bool GetNoServerPointer() { throw new ObjectDisposedException("ConnectionResult"); } - bool retVal = Raw.ConnectionResult.GetNoServerPointer(_inner); + Raw.ConnectorResultFfiResultBoolBoxIronRdpError result = Raw.ConnectionResult.GetNoServerPointer(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + bool retVal = result.Ok; return retVal; } } + /// public bool GetPointerSoftwareRendering() { unsafe @@ -156,7 +157,12 @@ public bool GetPointerSoftwareRendering() { throw new ObjectDisposedException("ConnectionResult"); } - bool retVal = Raw.ConnectionResult.GetPointerSoftwareRendering(_inner); + Raw.ConnectorResultFfiResultBoolBoxIronRdpError result = Raw.ConnectionResult.GetPointerSoftwareRendering(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + bool retVal = result.Ok; return retVal; } } diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/DecodedImage.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/DecodedImage.cs index e8e409911..737e62674 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/DecodedImage.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/DecodedImage.cs @@ -53,6 +53,20 @@ public unsafe DecodedImage(Raw.DecodedImage* handle) _inner = handle; } + /// + /// A DecodedImage allocated on Rust side. + /// + public static DecodedImage New(PixelFormat pixelFormat, ushort width, ushort height) + { + unsafe + { + Raw.PixelFormat pixelFormatRaw; + pixelFormatRaw = (Raw.PixelFormat)pixelFormat; + Raw.DecodedImage* retVal = Raw.DecodedImage.New(pixelFormatRaw, width, height); + return new DecodedImage(retVal); + } + } + /// /// A BytesSlice allocated on Rust side. /// diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/State.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/DynClientConnectorState.cs similarity index 73% rename from ffi/dotnet/Devolutions.IronRdp/Generated/State.cs rename to ffi/dotnet/Devolutions.IronRdp/Generated/DynClientConnectorState.cs index 7d9875390..447266b1d 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/State.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/DynClientConnectorState.cs @@ -11,9 +11,9 @@ namespace Devolutions.IronRdp; #nullable enable -public partial class State: IDisposable +public partial class DynClientConnectorState: IDisposable { - private unsafe Raw.State* _inner; + private unsafe Raw.DynClientConnectorState* _inner; public string Name { @@ -24,7 +24,7 @@ public string Name } /// - /// Creates a managed State from a raw handle. + /// Creates a managed DynClientConnectorState from a raw handle. /// /// /// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free). @@ -32,7 +32,7 @@ public string Name /// This constructor assumes the raw struct is allocated on Rust side. /// If implemented, the custom Drop implementation on Rust side WILL run on destruction. /// - public unsafe State(Raw.State* handle) + public unsafe DynClientConnectorState(Raw.DynClientConnectorState* handle) { _inner = handle; } @@ -44,9 +44,9 @@ public void GetName(DiplomatWriteable writeable) { if (_inner == null) { - throw new ObjectDisposedException("State"); + throw new ObjectDisposedException("DynClientConnectorState"); } - Raw.ConnectorFfiResultVoidBoxIronRdpError result = Raw.State.GetName(_inner, &writeable); + Raw.ConnectorFfiResultVoidBoxIronRdpError result = Raw.DynClientConnectorState.GetName(_inner, &writeable); if (!result.isOk) { throw new IronRdpException(new IronRdpError(result.Err)); @@ -61,10 +61,10 @@ public string GetName() { if (_inner == null) { - throw new ObjectDisposedException("State"); + throw new ObjectDisposedException("DynClientConnectorState"); } DiplomatWriteable writeable = new DiplomatWriteable(); - Raw.ConnectorFfiResultVoidBoxIronRdpError result = Raw.State.GetName(_inner, &writeable); + Raw.ConnectorFfiResultVoidBoxIronRdpError result = Raw.DynClientConnectorState.GetName(_inner, &writeable); if (!result.isOk) { throw new IronRdpException(new IronRdpError(result.Err)); @@ -81,9 +81,9 @@ public bool IsTerminal() { if (_inner == null) { - throw new ObjectDisposedException("State"); + throw new ObjectDisposedException("DynClientConnectorState"); } - bool retVal = Raw.State.IsTerminal(_inner); + bool retVal = Raw.DynClientConnectorState.IsTerminal(_inner); return retVal; } } @@ -91,7 +91,7 @@ public bool IsTerminal() /// /// Returns the underlying raw handle. /// - public unsafe Raw.State* AsFFI() + public unsafe Raw.DynClientConnectorState* AsFFI() { return _inner; } @@ -108,14 +108,14 @@ public void Dispose() return; } - Raw.State.Destroy(_inner); + Raw.DynClientConnectorState.Destroy(_inner); _inner = null; GC.SuppressFinalize(this); } } - ~State() + ~DynClientConnectorState() { Dispose(); } diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/IronRdpPdu.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/IronRdpPdu.cs index c80c47ac2..2bebeedeb 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/IronRdpPdu.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/IronRdpPdu.cs @@ -29,6 +29,18 @@ public unsafe IronRdpPdu(Raw.IronRdpPdu* handle) _inner = handle; } + /// + /// A IronRdpPdu allocated on Rust side. + /// + public static IronRdpPdu New() + { + unsafe + { + Raw.IronRdpPdu* retVal = Raw.IronRdpPdu.New(); + return new IronRdpPdu(retVal); + } + } + /// /// /// A PduInfo allocated on Rust side. diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/PixelFormat.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/PixelFormat.cs new file mode 100644 index 000000000..f952c6910 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/PixelFormat.cs @@ -0,0 +1,24 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp; + +#nullable enable + +public enum PixelFormat +{ + ARgb32 = 0, + XRgb32 = 1, + ABgr32 = 2, + XBgr32 = 3, + BgrA32 = 4, + BgrX32 = 5, + RgbA32 = 6, + RgbX32 = 7, +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStage.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStage.cs index c0b5e9116..a0f3d27ee 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStage.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStage.cs @@ -16,6 +16,9 @@ public partial struct ActiveStage { private const string NativeLib = "DevolutionsIronRdp"; + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStage_new", ExactSpelling = true)] + public static unsafe extern SessionFfiResultBoxActiveStageBoxIronRdpError New(ConnectionResult* connectionResult); + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStage_process", ExactSpelling = true)] public static unsafe extern SessionFfiResultBoxActiveStageOutputIteratorBoxIronRdpError Process(ActiveStage* self, DecodedImage* image, Action* action, byte* payload, nuint payloadSz); diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStageOutputIterator.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStageOutputIterator.cs index ef95053ac..1d7b4b20a 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStageOutputIterator.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStageOutputIterator.cs @@ -19,6 +19,10 @@ public partial struct ActiveStageOutputIterator [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStageOutputIterator_len", ExactSpelling = true)] public static unsafe extern nuint Len(ActiveStageOutputIterator* self); + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStageOutputIterator_is_empty", ExactSpelling = true)] + [return: MarshalAs(UnmanagedType.U1)] + public static unsafe extern bool IsEmpty(ActiveStageOutputIterator* self); + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStageOutputIterator_next", ExactSpelling = true)] public static unsafe extern ActiveStageOutput* Next(ActiveStageOutputIterator* self); diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawClientConnector.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawClientConnector.cs index ce46a8ddc..aa99c056f 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/RawClientConnector.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawClientConnector.cs @@ -58,8 +58,11 @@ public partial struct ClientConnector [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnector_next_pdu_hint", ExactSpelling = true)] public static unsafe extern ConnectorFfiResultOptBoxPduHintBoxIronRdpError NextPduHint(ClientConnector* self); - [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnector_state", ExactSpelling = true)] - public static unsafe extern ConnectorFfiResultBoxStateBoxIronRdpError State(ClientConnector* self); + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnector_get_dyn_state", ExactSpelling = true)] + public static unsafe extern ConnectorFfiResultBoxDynClientConnectorStateBoxIronRdpError GetDynState(ClientConnector* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnector_consume_self_and_get_state", ExactSpelling = true)] + public static unsafe extern ConnectorFfiResultBoxClientConnectorStateBoxIronRdpError ConsumeSelfAndGetState(ClientConnector* self); [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnector_destroy", ExactSpelling = true)] public static unsafe extern void Destroy(ClientConnector* self); diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawClientConnectorState.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawClientConnectorState.cs index da4fd6a0d..06e1dd417 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/RawClientConnectorState.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawClientConnectorState.cs @@ -34,12 +34,6 @@ public partial struct ClientConnectorState [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnectorState_get_basic_settings_exchange_wait_response_connect_initial", ExactSpelling = true)] public static unsafe extern ConnectorStateFfiResultBoxConnectInitialBoxIronRdpError GetBasicSettingsExchangeWaitResponseConnectInitial(ClientConnectorState* self); - [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnectorState_get_channel_connection_io_channel_id", ExactSpelling = true)] - public static unsafe extern ConnectorStateFfiResultU16BoxIronRdpError GetChannelConnectionIoChannelId(ClientConnectorState* self); - - [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnectorState_get_secure_settings_exchange_io_channel_id", ExactSpelling = true)] - public static unsafe extern ConnectorStateFfiResultU16BoxIronRdpError GetSecureSettingsExchangeIoChannelId(ClientConnectorState* self); - [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnectorState_get_connected_result", ExactSpelling = true)] public static unsafe extern ConnectorStateFfiResultBoxConnectionResultBoxIronRdpError GetConnectedResult(ClientConnectorState* self); diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectionResult.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectionResult.cs index c8f51e3d1..80c5b25ff 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectionResult.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectionResult.cs @@ -17,24 +17,19 @@ public partial struct ConnectionResult private const string NativeLib = "DevolutionsIronRdp"; [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConnectionResult_get_io_channel_id", ExactSpelling = true)] - public static unsafe extern ushort GetIoChannelId(ConnectionResult* self); + public static unsafe extern ConnectorResultFfiResultU16BoxIronRdpError GetIoChannelId(ConnectionResult* self); [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConnectionResult_get_user_channel_id", ExactSpelling = true)] - public static unsafe extern ushort GetUserChannelId(ConnectionResult* self); - - [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConnectionResult_get_static_channels", ExactSpelling = true)] - public static unsafe extern StaticChannelSet* GetStaticChannels(ConnectionResult* self); + public static unsafe extern ConnectorResultFfiResultU16BoxIronRdpError GetUserChannelId(ConnectionResult* self); [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConnectionResult_get_desktop_size", ExactSpelling = true)] - public static unsafe extern DesktopSize* GetDesktopSize(ConnectionResult* self); + public static unsafe extern ConnectorResultFfiResultBoxDesktopSizeBoxIronRdpError GetDesktopSize(ConnectionResult* self); [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConnectionResult_get_no_server_pointer", ExactSpelling = true)] - [return: MarshalAs(UnmanagedType.U1)] - public static unsafe extern bool GetNoServerPointer(ConnectionResult* self); + public static unsafe extern ConnectorResultFfiResultBoolBoxIronRdpError GetNoServerPointer(ConnectionResult* self); [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConnectionResult_get_pointer_software_rendering", ExactSpelling = true)] - [return: MarshalAs(UnmanagedType.U1)] - public static unsafe extern bool GetPointerSoftwareRendering(ConnectionResult* self); + public static unsafe extern ConnectorResultFfiResultBoolBoxIronRdpError GetPointerSoftwareRendering(ConnectionResult* self); [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConnectionResult_destroy", ExactSpelling = true)] public static unsafe extern void Destroy(ConnectionResult* self); diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoxClientConnectorStateBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoxClientConnectorStateBoxIronRdpError.cs new file mode 100644 index 000000000..4a9bf3275 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoxClientConnectorStateBoxIronRdpError.cs @@ -0,0 +1,46 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct ConnectorFfiResultBoxClientConnectorStateBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal ClientConnectorState* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe ClientConnectorState* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoxDynClientConnectorStateBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoxDynClientConnectorStateBoxIronRdpError.cs new file mode 100644 index 000000000..285db24d9 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoxDynClientConnectorStateBoxIronRdpError.cs @@ -0,0 +1,46 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct ConnectorFfiResultBoxDynClientConnectorStateBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal DynClientConnectorState* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe DynClientConnectorState* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoxStateBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorResultFfiResultBoolBoxIronRdpError.cs similarity index 85% rename from ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoxStateBoxIronRdpError.cs rename to ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorResultFfiResultBoolBoxIronRdpError.cs index 52c4cae5f..43f6e35f6 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoxStateBoxIronRdpError.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorResultFfiResultBoolBoxIronRdpError.cs @@ -12,13 +12,13 @@ namespace Devolutions.IronRdp.Raw; #nullable enable [StructLayout(LayoutKind.Sequential)] -public partial struct ConnectorFfiResultBoxStateBoxIronRdpError +public partial struct ConnectorResultFfiResultBoolBoxIronRdpError { [StructLayout(LayoutKind.Explicit)] private unsafe struct InnerUnion { [FieldOffset(0)] - internal State* ok; + internal bool ok; [FieldOffset(0)] internal IronRdpError* err; } @@ -28,7 +28,7 @@ private unsafe struct InnerUnion [MarshalAs(UnmanagedType.U1)] public bool isOk; - public unsafe State* Ok + public unsafe bool Ok { get { diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorResultFfiResultBoxDesktopSizeBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorResultFfiResultBoxDesktopSizeBoxIronRdpError.cs new file mode 100644 index 000000000..21b72d2b2 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorResultFfiResultBoxDesktopSizeBoxIronRdpError.cs @@ -0,0 +1,46 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct ConnectorResultFfiResultBoxDesktopSizeBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal DesktopSize* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe DesktopSize* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorStateFfiResultU16BoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorResultFfiResultU16BoxIronRdpError.cs similarity index 92% rename from ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorStateFfiResultU16BoxIronRdpError.cs rename to ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorResultFfiResultU16BoxIronRdpError.cs index d5d3402c8..6d2c9298f 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorStateFfiResultU16BoxIronRdpError.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorResultFfiResultU16BoxIronRdpError.cs @@ -12,7 +12,7 @@ namespace Devolutions.IronRdp.Raw; #nullable enable [StructLayout(LayoutKind.Sequential)] -public partial struct ConnectorStateFfiResultU16BoxIronRdpError +public partial struct ConnectorResultFfiResultU16BoxIronRdpError { [StructLayout(LayoutKind.Explicit)] private unsafe struct InnerUnion diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawDecodedImage.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawDecodedImage.cs index a07a74189..078af3845 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/RawDecodedImage.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawDecodedImage.cs @@ -16,6 +16,9 @@ public partial struct DecodedImage { private const string NativeLib = "DevolutionsIronRdp"; + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DecodedImage_new", ExactSpelling = true)] + public static unsafe extern DecodedImage* New(PixelFormat pixelFormat, ushort width, ushort height); + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DecodedImage_get_data", ExactSpelling = true)] public static unsafe extern BytesSlice* GetData(DecodedImage* self); diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawState.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawDynClientConnectorState.cs similarity index 55% rename from ffi/dotnet/Devolutions.IronRdp/Generated/RawState.cs rename to ffi/dotnet/Devolutions.IronRdp/Generated/RawDynClientConnectorState.cs index 99ea3e78f..c9dde4dae 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/RawState.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawDynClientConnectorState.cs @@ -12,17 +12,17 @@ namespace Devolutions.IronRdp.Raw; #nullable enable [StructLayout(LayoutKind.Sequential)] -public partial struct State +public partial struct DynClientConnectorState { private const string NativeLib = "DevolutionsIronRdp"; - [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "State_get_name", ExactSpelling = true)] - public static unsafe extern ConnectorFfiResultVoidBoxIronRdpError GetName(State* self, DiplomatWriteable* writeable); + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DynClientConnectorState_get_name", ExactSpelling = true)] + public static unsafe extern ConnectorFfiResultVoidBoxIronRdpError GetName(DynClientConnectorState* self, DiplomatWriteable* writeable); - [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "State_is_terminal", ExactSpelling = true)] + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DynClientConnectorState_is_terminal", ExactSpelling = true)] [return: MarshalAs(UnmanagedType.U1)] - public static unsafe extern bool IsTerminal(State* self); + public static unsafe extern bool IsTerminal(DynClientConnectorState* self); - [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "State_destroy", ExactSpelling = true)] - public static unsafe extern void Destroy(State* self); + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DynClientConnectorState_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(DynClientConnectorState* self); } diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawIronRdpPdu.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawIronRdpPdu.cs index 32a59b2f3..4e1ea99a2 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/RawIronRdpPdu.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawIronRdpPdu.cs @@ -16,6 +16,9 @@ public partial struct IronRdpPdu { private const string NativeLib = "DevolutionsIronRdp"; + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "IronRdpPdu_new", ExactSpelling = true)] + public static unsafe extern IronRdpPdu* New(); + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "IronRdpPdu_find_size", ExactSpelling = true)] public static unsafe extern PduFfiResultOptBoxPduInfoBoxIronRdpError FindSize(IronRdpPdu* self, byte* bytes, nuint bytesSz); diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawPixelFormat.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawPixelFormat.cs new file mode 100644 index 000000000..0cc53eaad --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawPixelFormat.cs @@ -0,0 +1,24 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +public enum PixelFormat +{ + ARgb32 = 0, + XRgb32 = 1, + ABgr32 = 2, + XBgr32 = 3, + BgrA32 = 4, + BgrX32 = 5, + RgbA32 = 6, + RgbX32 = 7, +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxActiveStageBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxActiveStageBoxIronRdpError.cs new file mode 100644 index 000000000..998d2eb08 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxActiveStageBoxIronRdpError.cs @@ -0,0 +1,46 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct SessionFfiResultBoxActiveStageBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal ActiveStage* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe ActiveStage* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/src/Connection.cs b/ffi/dotnet/Devolutions.IronRdp/src/Connection.cs new file mode 100644 index 000000000..7348e9284 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/src/Connection.cs @@ -0,0 +1,237 @@ + +using System.Net; +using System.Net.Security; +using System.Net.Sockets; +using Devolutions.IronRdp; + +public class Connection +{ + + public static async Task<(ConnectionResult,Framed)> Connect(string servername, string username, string password, string domain, int width, int height) + { + Config config = buildConfig(servername, username, password, domain, width, height); + + var stream = await CreateTcpConnection(servername, 3389); + var framed = new Framed(stream); + + ClientConnector connector = ClientConnector.New(config); + + var ip = await Dns.GetHostAddressesAsync(servername); + if (ip.Length == 0) + { + throw new IronRdpLibException(IronRdpLibExceptionType.CannotResolveDns, "Cannot resolve DNS to " + servername); + } + + var socketAddrString = ip[0].ToString() + ":3389"; + connector.WithServerAddr(socketAddrString); + + await connectBegin(framed, connector); + var (serverPublicKey, framedSsl) = await securityUpgrade(servername, framed, connector); + var result = await ConnectFinalize(servername, connector, serverPublicKey, framedSsl); + return (result, framedSsl); + } + + private static async Task<(byte[], Framed)> securityUpgrade(string servername, Framed framed, ClientConnector connector) + { + byte[] serverPublicKey; + Framed framedSsl; + var (streamRequireUpgrade, _) = framed.GetInner(); + var promise = new TaskCompletionSource(); + var sslStream = new SslStream(streamRequireUpgrade, false, (sender, certificate, chain, sslPolicyErrors) => + { + promise.SetResult(certificate!.GetPublicKey()); + return true; + }); + await sslStream.AuthenticateAsClientAsync(servername); + serverPublicKey = await promise.Task; + framedSsl = new Framed(sslStream); + connector.MarkSecurityUpgradeAsDone(); + + return (serverPublicKey, framedSsl); + } + + private static async Task connectBegin(Framed framed, ClientConnector connector) + { + var writeBuf = WriteBuf.New(); + while (!connector.ShouldPerformSecurityUpgrade()) + { + await SingleConnectStep(connector, writeBuf, framed); + } + } + + private static Config buildConfig(string servername, string username, string password, string domain, int width, int height) + { + ConfigBuilder configBuilder = ConfigBuilder.New(); + + configBuilder.WithUsernameAndPassword(username, password); + configBuilder.SetDomain(domain); + configBuilder.SetDesktopSize((ushort)height, (ushort)width); + configBuilder.SetClientName("IronRdp"); + configBuilder.SetClientDir("C:\\"); + configBuilder.SetPerformanceFlags(PerformanceFlags.NewDefault()); + + return configBuilder.Build(); + } + + private static async Task ConnectFinalize(string servername, ClientConnector connector, byte[] serverpubkey, Framed framedSsl) + { + var writeBuf2 = WriteBuf.New(); + if (connector.ShouldPerformCredssp()) + { + await PerformCredsspSteps(connector, servername, writeBuf2, framedSsl, serverpubkey); + } + while (!connector.GetDynState().IsTerminal()) + { + await SingleConnectStep(connector, writeBuf2, framedSsl); + } + + ClientConnectorState state = connector.ConsumeSelfAndGetState(); + + if (state.GetType() == ClientConnectorStateType.Connected) + { + return state.GetConnectedResult(); + } + else + { + throw new IronRdpLibException(IronRdpLibExceptionType.ConnectionFailed, "Connection failed"); + } + } + + private static async Task PerformCredsspSteps(ClientConnector connector, string serverName, WriteBuf writeBuf, Framed framedSsl, byte[] serverpubkey) + { + var credsspSequenceInitResult = CredsspSequence.Init(connector, serverName, serverpubkey, null); + var credsspSequence = credsspSequenceInitResult.GetCredsspSequence(); + var tsRequest = credsspSequenceInitResult.GetTsRequest(); + TcpClient tcpClient = new TcpClient(); + while (true) + { + var generator = credsspSequence.ProcessTsRequest(tsRequest); + var clientState = await ResolveGenerator(generator, tcpClient); + writeBuf.Clear(); + var written = credsspSequence.HandleProcessResult(clientState, writeBuf); + + if (written.GetSize().IsSome()) + { + var actualSize = (int)written.GetSize().Get(); + var response = new byte[actualSize]; + writeBuf.ReadIntoBuf(response); + await framedSsl.Write(response); + } + + var pduHint = credsspSequence.NextPduHint()!; + if (pduHint == null) + { + break; + } + + var pdu = await framedSsl.ReadByHint(pduHint); + var decoded = credsspSequence.DecodeServerMessage(pdu); + + if (null == decoded) + { + break; + } + + tsRequest = decoded; + } + } + + private static async Task ResolveGenerator(CredsspProcessGenerator generator, TcpClient tcpClient) + { + var state = generator.Start(); + NetworkStream stream = null; + while (true) + { + if (state.IsSuspended()) + { + var request = state.GetNetworkRequestIfSuspended()!; + var protocol = request.GetProtocol(); + var url = request.GetUrl(); + var data = request.GetData(); + if (null == stream) + { + url = url.Replace("tcp://", ""); + var split = url.Split(":"); + await tcpClient.ConnectAsync(split[0], int.Parse(split[1])); + stream = tcpClient.GetStream(); + + } + if (protocol == NetworkRequestProtocol.Tcp) + { + stream.Write(Utils.Vecu8ToByte(data)); + var readBuf = new byte[8096]; + var readlen = await stream.ReadAsync(readBuf, 0, readBuf.Length); + var actuallyRead = new byte[readlen]; + Array.Copy(readBuf, actuallyRead, readlen); + state = generator.Resume(actuallyRead); + } + else + { + throw new Exception("Unimplemented protocol"); + } + } + else + { + var client_state = state.GetClientStateIfCompleted(); + return client_state; + } + } + } + + static async Task SingleConnectStep(ClientConnector connector, WriteBuf buf, Framed framed) + where T : Stream + { + buf.Clear(); + + var pduHint = connector.NextPduHint(); + Written written; + if (pduHint != null) + { + byte[] pdu = await framed.ReadByHint(pduHint); + written = connector.Step(pdu, buf); + } + else + { + written = connector.StepNoInput(buf); + } + + if (written.GetWrittenType() == WrittenType.Nothing) + { + return; + } + + // will throw if size is not set + var size = written.GetSize().Get(); + + var response = new byte[size]; + buf.ReadIntoBuf(response); + + await framed.Write(response); + } + + static async Task CreateTcpConnection(String servername, int port) + { + IPHostEntry ipHostInfo = await Dns.GetHostEntryAsync(servername); + IPAddress ipAddress = ipHostInfo.AddressList[0]; + IPEndPoint ipEndPoint = new(ipAddress, port); + + TcpClient client = new TcpClient(); + + await client.ConnectAsync(ipEndPoint); + NetworkStream stream = client.GetStream(); + + return stream; + } + +} + +public static class Utils +{ + public static byte[] Vecu8ToByte(VecU8 vecU8) + { + var len = vecU8.GetSize(); + byte[] buffer = new byte[len]; + vecU8.Fill(buffer); + return buffer; + } +} \ No newline at end of file diff --git a/ffi/dotnet/Devolutions.IronRdp/src/Exceptions.cs b/ffi/dotnet/Devolutions.IronRdp/src/Exceptions.cs new file mode 100644 index 000000000..b03ba7338 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/src/Exceptions.cs @@ -0,0 +1,18 @@ +[Serializable] +public class IronRdpLibException : Exception +{ + public IronRdpLibExceptionType type { get; private set; } + + public IronRdpLibException(IronRdpLibExceptionType type, string message): base(message) + { + this.type = type; + } + +} + +public enum IronRdpLibExceptionType +{ + CannotResolveDns, + ConnectionFailed, + EndOfFile, +} \ No newline at end of file diff --git a/ffi/dotnet/Devolutions.IronRdp/src/Framed.cs b/ffi/dotnet/Devolutions.IronRdp/src/Framed.cs index 715b05407..c31763df3 100644 --- a/ffi/dotnet/Devolutions.IronRdp/src/Framed.cs +++ b/ffi/dotnet/Devolutions.IronRdp/src/Framed.cs @@ -1,3 +1,4 @@ +using System.Linq.Expressions; using System.Runtime.InteropServices; using Devolutions.IronRdp; @@ -17,6 +18,24 @@ public Framed(S stream) return (this.stream, this.buffer); } + public async Task<(Devolutions.IronRdp.Action,byte[])> ReadPdu() { + + while(true) { + var pduInfo = IronRdpPdu.New().FindSize(this.buffer.ToArray()); + if (null != pduInfo) { + var frame = await this.ReadExact(pduInfo.GetLength()); + var action = pduInfo.GetAction(); + return (action,frame); + }else { + var len = await this.Read(); + + if (len == 0) { + throw new IronRdpLibException(IronRdpLibExceptionType.EndOfFile,"EOF on ReadPdu"); + } + } + } + } + /// /// Returns a span that represents a portion of the underlying buffer without modifying it. /// diff --git a/ffi/src/connector/mod.rs b/ffi/src/connector/mod.rs index 633282a75..a1d03b6b4 100644 --- a/ffi/src/connector/mod.rs +++ b/ffi/src/connector/mod.rs @@ -16,7 +16,7 @@ pub mod ffi { pdu::ffi::WriteBuf, }; - use super::{config::ffi::Config, result::ffi::Written}; + use super::{config::ffi::Config, result::ffi::Written, state::ffi::ClientConnectorState}; #[diplomat::opaque] // We must use Option here, as ClientConnector is not Clone and have functions that consume it pub struct ClientConnector(pub Option); @@ -132,9 +132,9 @@ pub mod ffi { } #[diplomat::opaque] - pub struct State<'a>(pub &'a dyn ironrdp::connector::State); + pub struct DynClientConnectorState<'a>(pub &'a dyn ironrdp::connector::State); - impl<'a> State<'a> { + impl<'a> DynClientConnectorState<'a> { pub fn get_name(&'a self, writeable: &'a mut DiplomatWriteable) -> Result<(), Box> { let name = self.0.name(); write!(writeable, "{}", name)?; @@ -154,11 +154,18 @@ pub mod ffi { Ok(connector.next_pdu_hint().map(PduHint).map(Box::new)) } - pub fn state(&self) -> Result>, Box> { + pub fn get_dyn_state(&self) -> Result>, Box> { let Some(connector) = self.0.as_ref() else { return Err(ValueConsumedError::for_item("connector").into()); }; - Ok(Box::new(State(connector.state()))) + Ok(Box::new(DynClientConnectorState(connector.state()))) + } + + pub fn consume_self_and_get_state(&mut self) -> Result, Box> { + let Some(connector) = self.0.take() else { + return Err(ValueConsumedError::for_item("connector").into()); + }; + Ok(Box::new(ClientConnectorState(Some(connector.state)))) } } @@ -169,5 +176,7 @@ pub mod ffi { pub struct LicenseExchangeSequence(pub ironrdp::connector::LicenseExchangeSequence); #[diplomat::opaque] - pub struct ConnectionActivationSequence(pub Box); + pub struct ConnectionActivationSequence( + pub Box, + ); } diff --git a/ffi/src/connector/result.rs b/ffi/src/connector/result.rs index ba86ba276..54211cc34 100644 --- a/ffi/src/connector/result.rs +++ b/ffi/src/connector/result.rs @@ -1,6 +1,10 @@ #[diplomat::bridge] pub mod ffi { - use crate::{connector::config::ffi::DesktopSize, utils::ffi::OptionalUsize}; + use crate::{ + connector::config::ffi::DesktopSize, + error::{ffi::IronRdpError, ValueConsumedError}, + utils::ffi::OptionalUsize, + }; #[diplomat::opaque] pub struct Written(pub ironrdp::connector::Written); @@ -27,31 +31,48 @@ pub mod ffi { } #[diplomat::opaque] - pub struct ConnectionResult<'a>(pub &'a ironrdp::connector::ConnectionResult); + pub struct ConnectionResult(pub Option); - impl<'a> ConnectionResult<'a> { - pub fn get_io_channel_id(&self) -> u16 { - self.0.io_channel_id + impl ConnectionResult { + pub fn get_io_channel_id(&self) -> Result> { + Ok(self + .0 + .as_ref() + .ok_or_else(|| ValueConsumedError::for_item("ConnectionResult"))? + .io_channel_id) } - pub fn get_user_channel_id(&self) -> u16 { - self.0.user_channel_id + pub fn get_user_channel_id(&self) -> Result> { + Ok(self + .0 + .as_ref() + .ok_or_else(|| ValueConsumedError::for_item("ConnectionResult"))? + .user_channel_id) } - pub fn get_static_channels(&'a self) -> Box> { - Box::new(crate::svc::ffi::StaticChannelSet(&self.0.static_channels)) + pub fn get_desktop_size(&self) -> Result, Box> { + Ok(Box::new(DesktopSize( + self.0 + .as_ref() + .ok_or_else(|| ValueConsumedError::for_item("ConnectionResult"))? + .desktop_size, + ))) } - pub fn get_desktop_size(&self) -> Box { - Box::new(DesktopSize(self.0.desktop_size)) + pub fn get_no_server_pointer(&self) -> Result> { + Ok(self + .0 + .as_ref() + .ok_or_else(|| ValueConsumedError::for_item("ConnectionResult"))? + .no_server_pointer) } - pub fn get_no_server_pointer(&self) -> bool { - self.0.no_server_pointer - } - - pub fn get_pointer_software_rendering(&self) -> bool { - self.0.pointer_software_rendering + pub fn get_pointer_software_rendering(&self) -> Result> { + Ok(self + .0 + .as_ref() + .ok_or_else(|| ValueConsumedError::for_item("ConnectionResult"))? + .pointer_software_rendering) } } } diff --git a/ffi/src/connector/state.rs b/ffi/src/connector/state.rs index 34997face..1536e99e8 100644 --- a/ffi/src/connector/state.rs +++ b/ffi/src/connector/state.rs @@ -1,9 +1,12 @@ #[diplomat::bridge] pub mod ffi { - use crate::{error::ffi::IronRdpError, pdu::ffi::SecurityProtocol}; + use crate::{ + error::{ffi::IronRdpError, ValueConsumedError}, + pdu::ffi::SecurityProtocol, + }; #[diplomat::opaque] - pub struct ClientConnectorState(pub ironrdp::connector::ClientConnectorState); + pub struct ClientConnectorState(pub Option); pub enum ClientConnectorStateType { Consumed, @@ -25,7 +28,11 @@ pub mod ffi { impl ClientConnectorState { pub fn get_type(&self) -> Result> { - let res = match &self.0 { + let res = match &self + .0 + .as_ref() + .ok_or_else(|| ValueConsumedError::for_item("ClientConnectorState"))? + { ironrdp::connector::ClientConnectorState::Consumed => ClientConnectorStateType::Consumed, ironrdp::connector::ClientConnectorState::ConnectionInitiationSendRequest => { ClientConnectorStateType::ConnectionInitiationSendRequest @@ -72,11 +79,15 @@ pub mod ffi { } pub fn get_connection_initiation_wait_confirm_requested_protocol( - &self, + &mut self, ) -> Result, Box> { - match &self.0 { + match self + .0 + .take() + .ok_or_else(|| ValueConsumedError::for_item("ClientConnectorState"))? + { ironrdp::connector::ClientConnectorState::ConnectionInitiationWaitConfirm { requested_protocol } => { - Ok(SecurityProtocol(*requested_protocol)) + Ok(SecurityProtocol(requested_protocol)) } _ => Err("Not in ConnectionInitiationWaitConfirm state".into()), } @@ -84,23 +95,29 @@ pub mod ffi { } pub fn get_enhanced_security_upgrade_selected_protocol( - &self, + &mut self, ) -> Result, Box> { - match &self.0 { + match self + .0 + .take() + .ok_or_else(|| ValueConsumedError::for_item("ClientConnectorState"))? + { ironrdp::connector::ClientConnectorState::EnhancedSecurityUpgrade { selected_protocol } => { - Ok(SecurityProtocol(*selected_protocol)) + Ok(SecurityProtocol(selected_protocol)) } _ => Err("Not in EnhancedSecurityUpgrade state".into()), } .map(Box::new) } - pub fn get_credssp_selected_protocol( - &self, - ) -> Result, Box> { - match &self.0 { + pub fn get_credssp_selected_protocol(&mut self) -> Result, Box> { + match self + .0 + .take() + .ok_or_else(|| ValueConsumedError::for_item("ClientConnectorState"))? + { ironrdp::connector::ClientConnectorState::Credssp { selected_protocol } => { - Ok(SecurityProtocol(*selected_protocol)) + Ok(SecurityProtocol(selected_protocol)) } _ => Err("Not in Credssp state".into()), } @@ -108,11 +125,15 @@ pub mod ffi { } pub fn get_basic_settings_exchange_send_initial_selected_protocol( - &self, + &mut self, ) -> Result, Box> { - match &self.0 { + match self + .0 + .take() + .ok_or_else(|| ValueConsumedError::for_item("ClientConnectorState"))? + { ironrdp::connector::ClientConnectorState::BasicSettingsExchangeSendInitial { selected_protocol } => { - Ok(SecurityProtocol(*selected_protocol)) + Ok(SecurityProtocol(selected_protocol)) } _ => Err("Not in BasicSettingsExchangeSendInitial state".into()), } @@ -120,46 +141,36 @@ pub mod ffi { } pub fn get_basic_settings_exchange_wait_response_connect_initial( - &self, + &mut self, ) -> Result, Box> { - match &self.0 { + match self + .0 + .take() + .ok_or_else(|| ValueConsumedError::for_item("ClientConnectorState"))? + { ironrdp::connector::ClientConnectorState::BasicSettingsExchangeWaitResponse { connect_initial } => { - Ok(crate::pdu::ffi::ConnectInitial(connect_initial.clone())) + Ok(crate::pdu::ffi::ConnectInitial(connect_initial)) } _ => Err("Not in BasicSettingsExchangeWaitResponse state".into()), } .map(Box::new) } - pub fn get_channel_connection_io_channel_id(&self) -> Result> { - match &self.0 { - ironrdp::connector::ClientConnectorState::ChannelConnection { io_channel_id, .. } => Ok(*io_channel_id), - _ => Err("Not in ChannelConnection state".into()), - } - } - - pub fn get_secure_settings_exchange_io_channel_id(&self) -> Result> { - match &self.0 { - ironrdp::connector::ClientConnectorState::SecureSettingsExchange { io_channel_id, .. } => { - Ok(*io_channel_id) - } - _ => Err("Not in SecureSettingsExchange state".into()), - } - } - // TODO: Add more getters for other states - pub fn get_connected_result<'a>( - &'a self, - ) -> Result>, Box> - { - match &self.0 { - ironrdp::connector::ClientConnectorState::Connected { result } => Ok(Box::new( - crate::connector::result::ffi::ConnectionResult(result), - )), + pub fn get_connected_result( + &mut self, + ) -> Result, Box> { + match self + .0 + .take() + .ok_or_else(|| ValueConsumedError::for_item("ClientConnectorState"))? + { + ironrdp::connector::ClientConnectorState::Connected { result } => { + Ok(Box::new(crate::connector::result::ffi::ConnectionResult(Some(result)))) + } _ => Err("Not in Connected state".into()), } } } - } diff --git a/ffi/src/graphics.rs b/ffi/src/graphics.rs index ae1016f6c..24a7f59a6 100644 --- a/ffi/src/graphics.rs +++ b/ffi/src/graphics.rs @@ -1,4 +1,3 @@ - #[diplomat::bridge] pub mod ffi { use std::rc::Rc; @@ -25,8 +24,8 @@ pub mod ffi { self.0.hotspot_y } - pub fn get_data<'a>(&'a self) -> Box> { + pub fn get_data(&self) -> Box> { Box::new(BytesSlice(&self.0.bitmap_data)) } } -} \ No newline at end of file +} diff --git a/ffi/src/input.rs b/ffi/src/input.rs index df65f2a69..0e5b6ee39 100644 --- a/ffi/src/input.rs +++ b/ffi/src/input.rs @@ -1,4 +1,3 @@ - #[diplomat::bridge] pub mod ffi { #[diplomat::opaque] @@ -8,6 +7,5 @@ pub mod ffi { pub fn new() -> Box { Box::new(Database(ironrdp::input::Database::new())) } - } -} \ No newline at end of file +} diff --git a/ffi/src/lib.rs b/ffi/src/lib.rs index 9ab8db7a0..4ae79f542 100644 --- a/ffi/src/lib.rs +++ b/ffi/src/lib.rs @@ -4,9 +4,9 @@ pub mod connector; pub mod credssp; pub mod dvc; pub mod error; +pub mod graphics; +pub mod input; pub mod pdu; +pub mod session; pub mod svc; pub mod utils; -pub mod session; -pub mod graphics; -pub mod input; \ No newline at end of file diff --git a/ffi/src/pdu.rs b/ffi/src/pdu.rs index 2ad6309c7..57bb11555 100644 --- a/ffi/src/pdu.rs +++ b/ffi/src/pdu.rs @@ -50,6 +50,10 @@ pub mod ffi { pub struct Action(pub ironrdp::pdu::Action); impl IronRdpPdu { + pub fn new() -> Box { + Box::new(IronRdpPdu) + } + pub fn find_size(&self, bytes: &[u8]) -> Result>, Box> { Ok(ironrdp::pdu::find_size(bytes)?.map(PduInfo).map(Box::new)) } diff --git a/ffi/src/session/image.rs b/ffi/src/session/image.rs index 6b700fc34..c8654e52e 100644 --- a/ffi/src/session/image.rs +++ b/ffi/src/session/image.rs @@ -2,13 +2,20 @@ pub mod ffi { use crate::utils::ffi::BytesSlice; - #[diplomat::opaque] - pub struct DecodedImage<'a>(pub &'a mut ironrdp::session::image::DecodedImage); + pub struct DecodedImage(pub ironrdp::session::image::DecodedImage); + + impl DecodedImage { + pub fn new(pixel_format: PixelFormat, width: u16, height: u16) -> Box { + Box::new(DecodedImage(ironrdp::session::image::DecodedImage::new( + pixel_format.into(), + width, + height, + ))) + } - impl<'a> DecodedImage<'a> { // The bytes array lives as long as the DecodedImage - pub fn get_data(&'a self) -> Box>{ + pub fn get_data(&self) -> Box> { Box::new(BytesSlice(self.0.data())) } @@ -20,4 +27,16 @@ pub mod ffi { self.0.height() } } -} \ No newline at end of file + + #[diplomat::enum_convert(ironrdp::graphics::image_processing::PixelFormat)] + pub enum PixelFormat { + ARgb32, + XRgb32, + ABgr32, + XBgr32, + BgrA32, + BgrX32, + RgbA32, + RgbX32, + } +} diff --git a/ffi/src/session/mod.rs b/ffi/src/session/mod.rs index 1a83742a4..0f9deb9b8 100644 --- a/ffi/src/session/mod.rs +++ b/ffi/src/session/mod.rs @@ -1,10 +1,15 @@ +#![allow(clippy::should_implement_trait)] // Diplomat doesn't support traits yet pub mod image; #[diplomat::bridge] pub mod ffi { use crate::{ - connector::ffi::ConnectionActivationSequence, error::ffi::IronRdpError, graphics::ffi::DecodedPointer, pdu::ffi::{Action, InclusiveRectangle}, utils::ffi::{BytesSlice, Position} + connector::{ffi::ConnectionActivationSequence, result::ffi::ConnectionResult}, + error::{ffi::IronRdpError, ValueConsumedError}, + graphics::ffi::DecodedPointer, + pdu::ffi::{Action, InclusiveRectangle}, + utils::ffi::{BytesSlice, Position}, }; use super::image::ffi::DecodedImage; @@ -23,19 +28,32 @@ pub mod ffi { self.0.len() } + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + pub fn next(&mut self) -> Option> { self.0.pop().map(ActiveStageOutput).map(Box::new) } } impl ActiveStage { + pub fn new(connection_result: &mut ConnectionResult) -> Result, Box> { + Ok(Box::new(ActiveStage(ironrdp::session::ActiveStage::new( + connection_result + .0 + .take() + .ok_or_else(|| ValueConsumedError::for_item("connection_result"))?, + )))) + } + pub fn process( &mut self, image: &mut DecodedImage, action: &Action, payload: &[u8], ) -> Result, Box> { - let outputs = self.0.process(image.0, action.0, payload)?; + let outputs = self.0.process(&mut image.0, action.0, payload)?; Ok(Box::new(ActiveStageOutputIterator(outputs))) } } @@ -65,7 +83,7 @@ pub mod ffi { } } - pub fn get_response_frame<'a>(&'a self) -> Option>> { + pub fn get_response_frame(&self) -> Option>> { match &self.0 { ironrdp::session::ActiveStageOutput::ResponseFrame(frame) => Some(Box::new(BytesSlice(frame))), _ => None, @@ -92,24 +110,29 @@ pub mod ffi { pub fn get_pointer_butmap(&self) -> Option> { match &self.0 { ironrdp::session::ActiveStageOutput::PointerBitmap(decoded_pointer) => { - Some(DecodedPointer(decoded_pointer.clone())) + Some(DecodedPointer(std::rc::Rc::clone(decoded_pointer))) } _ => None, - }.map(Box::new) + } + .map(Box::new) } pub fn get_terminate(&self) -> Option> { match &self.0 { - ironrdp::session::ActiveStageOutput::Terminate(reason) => Some(GracefulDisconnectReason(reason.clone())), + ironrdp::session::ActiveStageOutput::Terminate(reason) => Some(GracefulDisconnectReason(*reason)), _ => None, - }.map(Box::new) + } + .map(Box::new) } pub fn get_deactivate_all(&self) -> Option> { match &self.0 { - ironrdp::session::ActiveStageOutput::DeactivateAll(cas) => Some(ConnectionActivationSequence(cas.clone())), + ironrdp::session::ActiveStageOutput::DeactivateAll(cas) => { + Some(ConnectionActivationSequence(cas.clone())) + } _ => None, - }.map(Box::new) + } + .map(Box::new) } } diff --git a/ffi/src/utils/mod.rs b/ffi/src/utils/mod.rs index 2e872f12a..66bd58806 100644 --- a/ffi/src/utils/mod.rs +++ b/ffi/src/utils/mod.rs @@ -40,10 +40,9 @@ pub mod ffi { if buffer.len() < self.0.len() { return Err("Buffer is too small".into()); } - buffer.copy_from_slice(&self.0); + buffer.copy_from_slice(self.0); Ok(()) } - } #[diplomat::opaque] @@ -58,15 +57,15 @@ pub mod ffi { if buffer.len() < self.0.len() { return Err("Buffer is too small".into()); } - buffer.copy_from_slice(&self.0); + buffer.copy_from_slice(self.0); Ok(()) } } #[diplomat::opaque] - pub struct Position{ + pub struct Position { pub x: u16, - pub y: u16 + pub y: u16, } impl Position { @@ -91,5 +90,4 @@ pub mod ffi { self.0.ok_or_else(|| "Value is None".into()) } } - } From 0d9c65afbd3c3c7b55f55fd51d92dedc847c12d9 Mon Sep 17 00:00:00 2001 From: irving ou Date: Sun, 7 Apr 2024 22:12:14 -0400 Subject: [PATCH 10/18] update Connect method --- .../Program.cs | 18 +++++++++++++++++- .../Devolutions.IronRdp/src/Connection.cs | 16 +--------------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Program.cs b/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Program.cs index e435557c4..efcc4b997 100644 --- a/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Program.cs +++ b/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Program.cs @@ -21,7 +21,7 @@ static async Task Main(string[] args) var domain = arguments["--domain"]; try { - var (res, framed) = await Connection.Connect(serverName, username, password, domain, 1980, 1080); + var (res, framed) = await Connection.Connect(buildConfig(serverName, username, password, domain, 1980, 1080), serverName); var decodedImage = DecodedImage.New(PixelFormat.RgbA32, res.GetDesktopSize().GetWidth(), res.GetDesktopSize().GetHeight()); var activeState = ActiveStage.New(res); var keepLooping = true; @@ -177,5 +177,21 @@ static void PrintHelp() Console.WriteLine(" --help Show this message and exit."); } + + + private static Config buildConfig(string servername, string username, string password, string domain, int width, int height) + { + ConfigBuilder configBuilder = ConfigBuilder.New(); + + configBuilder.WithUsernameAndPassword(username, password); + configBuilder.SetDomain(domain); + configBuilder.SetDesktopSize((ushort)height, (ushort)width); + configBuilder.SetClientName("IronRdp"); + configBuilder.SetClientDir("C:\\"); + configBuilder.SetPerformanceFlags(PerformanceFlags.NewDefault()); + + return configBuilder.Build(); + } + } } \ No newline at end of file diff --git a/ffi/dotnet/Devolutions.IronRdp/src/Connection.cs b/ffi/dotnet/Devolutions.IronRdp/src/Connection.cs index 7348e9284..ea8519d07 100644 --- a/ffi/dotnet/Devolutions.IronRdp/src/Connection.cs +++ b/ffi/dotnet/Devolutions.IronRdp/src/Connection.cs @@ -7,9 +7,8 @@ public class Connection { - public static async Task<(ConnectionResult,Framed)> Connect(string servername, string username, string password, string domain, int width, int height) + public static async Task<(ConnectionResult,Framed)> Connect(Config config,string servername) { - Config config = buildConfig(servername, username, password, domain, width, height); var stream = await CreateTcpConnection(servername, 3389); var framed = new Framed(stream); @@ -59,19 +58,6 @@ private static async Task connectBegin(Framed framed, ClientConne } } - private static Config buildConfig(string servername, string username, string password, string domain, int width, int height) - { - ConfigBuilder configBuilder = ConfigBuilder.New(); - - configBuilder.WithUsernameAndPassword(username, password); - configBuilder.SetDomain(domain); - configBuilder.SetDesktopSize((ushort)height, (ushort)width); - configBuilder.SetClientName("IronRdp"); - configBuilder.SetClientDir("C:\\"); - configBuilder.SetPerformanceFlags(PerformanceFlags.NewDefault()); - - return configBuilder.Build(); - } private static async Task ConnectFinalize(string servername, ClientConnector connector, byte[] serverpubkey, Framed framedSsl) { From 545216a994dfa09049b3eb9ccbf39293683f7165 Mon Sep 17 00:00:00 2001 From: "irvingouj @ Devolutions" <139169536+irvingoujAtDevolution@users.noreply.github.com> Date: Mon, 8 Apr 2024 20:02:56 -0400 Subject: [PATCH 11/18] Update ffi/src/connector/mod.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Benoît Cortier --- ffi/src/connector/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ffi/src/connector/mod.rs b/ffi/src/connector/mod.rs index a1d03b6b4..a793dacfb 100644 --- a/ffi/src/connector/mod.rs +++ b/ffi/src/connector/mod.rs @@ -161,7 +161,7 @@ pub mod ffi { Ok(Box::new(DynClientConnectorState(connector.state()))) } - pub fn consume_self_and_get_state(&mut self) -> Result, Box> { + pub fn consume_and_cast_to_client_connector_state(&mut self) -> Result, Box> { let Some(connector) = self.0.take() else { return Err(ValueConsumedError::for_item("connector").into()); }; From aabf30e39418bd1f0a79d16cd199bd004f21cf92 Mon Sep 17 00:00:00 2001 From: "irvingouj @ Devolutions" <139169536+irvingoujAtDevolution@users.noreply.github.com> Date: Mon, 8 Apr 2024 20:03:29 -0400 Subject: [PATCH 12/18] Update ffi/src/session/mod.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Benoît Cortier --- ffi/src/session/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ffi/src/session/mod.rs b/ffi/src/session/mod.rs index 0f9deb9b8..a8e3caebe 100644 --- a/ffi/src/session/mod.rs +++ b/ffi/src/session/mod.rs @@ -107,7 +107,7 @@ pub mod ffi { .map(Box::new) } - pub fn get_pointer_butmap(&self) -> Option> { + pub fn get_pointer_bitmap(&self) -> Option> { match &self.0 { ironrdp::session::ActiveStageOutput::PointerBitmap(decoded_pointer) => { Some(DecodedPointer(std::rc::Rc::clone(decoded_pointer))) From 4115ad5630dd1618f4a5bd3493bc1052935d6ff6 Mon Sep 17 00:00:00 2001 From: "irvingouj @ Devolutions" <139169536+irvingoujAtDevolution@users.noreply.github.com> Date: Mon, 8 Apr 2024 20:03:38 -0400 Subject: [PATCH 13/18] Update ffi/src/connector/state.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Benoît Cortier --- ffi/src/connector/state.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ffi/src/connector/state.rs b/ffi/src/connector/state.rs index 1536e99e8..9241d9634 100644 --- a/ffi/src/connector/state.rs +++ b/ffi/src/connector/state.rs @@ -89,7 +89,7 @@ pub mod ffi { ironrdp::connector::ClientConnectorState::ConnectionInitiationWaitConfirm { requested_protocol } => { Ok(SecurityProtocol(requested_protocol)) } - _ => Err("Not in ConnectionInitiationWaitConfirm state".into()), + _ => Err("not in ConnectionInitiationWaitConfirm state".into()), } .map(Box::new) } From 8647fc7bdb3708f7d68a7a2229e5b7b3b5666d27 Mon Sep 17 00:00:00 2001 From: "irvingouj @ Devolutions" <139169536+irvingoujAtDevolution@users.noreply.github.com> Date: Mon, 8 Apr 2024 20:03:57 -0400 Subject: [PATCH 14/18] Update ffi/src/session/mod.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Benoît Cortier --- ffi/src/session/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ffi/src/session/mod.rs b/ffi/src/session/mod.rs index a8e3caebe..b7c9f3908 100644 --- a/ffi/src/session/mod.rs +++ b/ffi/src/session/mod.rs @@ -1,4 +1,4 @@ -#![allow(clippy::should_implement_trait)] // Diplomat doesn't support traits yet +#![allow(clippy::should_implement_trait)] // Implementing extra traits is not useful for FFI pub mod image; #[diplomat::bridge] From 1137a4cbd6698d01a13b4f2125c5efa7b190d1c7 Mon Sep 17 00:00:00 2001 From: irving ou Date: Mon, 8 Apr 2024 20:40:18 -0400 Subject: [PATCH 15/18] Review fix --- .../Generated/ActiveStageOutput.cs | 76 ++++++++++------- .../Generated/ClientConnector.cs | 16 ++-- ...DynClientConnectorState.cs => DynState.cs} | 26 +++--- .../{Database.cs => InputDatabase.cs} | 22 ++--- .../Generated/IronRdpErrorKind.cs | 1 + .../Devolutions.IronRdp/Generated/Position.cs | 84 ++++++------------- .../Generated/RawActiveStageOutput.cs | 14 ++-- .../Generated/RawClientConnector.cs | 6 +- ...torFfiResultBoxDynStateBoxIronRdpError.cs} | 6 +- ...ClientConnectorState.cs => RawDynState.cs} | 14 ++-- .../{RawDatabase.cs => RawInputDatabase.cs} | 10 +-- .../Generated/RawIronRdpErrorKind.cs | 1 + .../Generated/RawPosition.cs | 9 +- ...onFfiResultBoxBytesSliceBoxIronRdpError.cs | 46 ++++++++++ ...ectionActivationSequenceBoxIronRdpError.cs | 46 ++++++++++ ...iResultBoxDecodedPointerBoxIronRdpError.cs | 46 ++++++++++ ...GracefulDisconnectReasonBoxIronRdpError.cs | 46 ++++++++++ ...ultBoxInclusiveRectangleBoxIronRdpError.cs | 46 ++++++++++ ...SessionFfiResultPositionBoxIronRdpError.cs | 46 ++++++++++ .../Devolutions.IronRdp/src/Connection.cs | 4 +- ffi/src/connector/config.rs | 10 +-- ffi/src/connector/mod.rs | 12 +-- ffi/src/connector/state.rs | 26 ++++-- ffi/src/error.rs | 42 ++++++++++ ffi/src/input.rs | 8 +- ffi/src/lib.rs | 1 + ffi/src/session/mod.rs | 52 +++++++----- ffi/src/utils/mod.rs | 19 +---- 28 files changed, 520 insertions(+), 215 deletions(-) rename ffi/dotnet/Devolutions.IronRdp/Generated/{DynClientConnectorState.cs => DynState.cs} (73%) rename ffi/dotnet/Devolutions.IronRdp/Generated/{Database.cs => InputDatabase.cs} (69%) rename ffi/dotnet/Devolutions.IronRdp/Generated/{RawConnectorFfiResultBoxDynClientConnectorStateBoxIronRdpError.cs => RawConnectorFfiResultBoxDynStateBoxIronRdpError.cs} (80%) rename ffi/dotnet/Devolutions.IronRdp/Generated/{RawDynClientConnectorState.cs => RawDynState.cs} (55%) rename ffi/dotnet/Devolutions.IronRdp/Generated/{RawDatabase.cs => RawInputDatabase.cs} (61%) create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxBytesSliceBoxIronRdpError.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxConnectionActivationSequenceBoxIronRdpError.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxDecodedPointerBoxIronRdpError.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxGracefulDisconnectReasonBoxIronRdpError.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxInclusiveRectangleBoxIronRdpError.cs create mode 100644 ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultPositionBoxIronRdpError.cs diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStageOutput.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStageOutput.cs index 79390a827..4bc7022b3 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStageOutput.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/ActiveStageOutput.cs @@ -15,7 +15,7 @@ public partial class ActiveStageOutput: IDisposable { private unsafe Raw.ActiveStageOutput* _inner; - public ConnectionActivationSequence? DeactivateAll + public ConnectionActivationSequence DeactivateAll { get { @@ -23,7 +23,7 @@ public ConnectionActivationSequence? DeactivateAll } } - public InclusiveRectangle? GraphicsUpdate + public InclusiveRectangle GraphicsUpdate { get { @@ -31,15 +31,15 @@ public InclusiveRectangle? GraphicsUpdate } } - public DecodedPointer? PointerButmap + public DecodedPointer PointerBitmap { get { - return GetPointerButmap(); + return GetPointerBitmap(); } } - public Position? PointerPosition + public Position PointerPosition { get { @@ -47,7 +47,7 @@ public Position? PointerPosition } } - public BytesSlice? ResponseFrame + public BytesSlice ResponseFrame { get { @@ -55,7 +55,7 @@ public BytesSlice? ResponseFrame } } - public GracefulDisconnectReason? Terminate + public GracefulDisconnectReason Terminate { get { @@ -101,10 +101,11 @@ public ActiveStageOutputType GetType() } } + /// /// /// A BytesSlice allocated on Rust side. /// - public BytesSlice? GetResponseFrame() + public BytesSlice GetResponseFrame() { unsafe { @@ -112,19 +113,21 @@ public ActiveStageOutputType GetType() { throw new ObjectDisposedException("ActiveStageOutput"); } - Raw.BytesSlice* retVal = Raw.ActiveStageOutput.GetResponseFrame(_inner); - if (retVal == null) + Raw.SessionFfiResultBoxBytesSliceBoxIronRdpError result = Raw.ActiveStageOutput.GetResponseFrame(_inner); + if (!result.isOk) { - return null; + throw new IronRdpException(new IronRdpError(result.Err)); } + Raw.BytesSlice* retVal = result.Ok; return new BytesSlice(retVal); } } + /// /// /// A InclusiveRectangle allocated on Rust side. /// - public InclusiveRectangle? GetGraphicsUpdate() + public InclusiveRectangle GetGraphicsUpdate() { unsafe { @@ -132,19 +135,21 @@ public ActiveStageOutputType GetType() { throw new ObjectDisposedException("ActiveStageOutput"); } - Raw.InclusiveRectangle* retVal = Raw.ActiveStageOutput.GetGraphicsUpdate(_inner); - if (retVal == null) + Raw.SessionFfiResultBoxInclusiveRectangleBoxIronRdpError result = Raw.ActiveStageOutput.GetGraphicsUpdate(_inner); + if (!result.isOk) { - return null; + throw new IronRdpException(new IronRdpError(result.Err)); } + Raw.InclusiveRectangle* retVal = result.Ok; return new InclusiveRectangle(retVal); } } + /// /// - /// A Position allocated on Rust side. + /// A Position allocated on C# side. /// - public Position? GetPointerPosition() + public Position GetPointerPosition() { unsafe { @@ -152,19 +157,21 @@ public ActiveStageOutputType GetType() { throw new ObjectDisposedException("ActiveStageOutput"); } - Raw.Position* retVal = Raw.ActiveStageOutput.GetPointerPosition(_inner); - if (retVal == null) + Raw.SessionFfiResultPositionBoxIronRdpError result = Raw.ActiveStageOutput.GetPointerPosition(_inner); + if (!result.isOk) { - return null; + throw new IronRdpException(new IronRdpError(result.Err)); } + Raw.Position retVal = result.Ok; return new Position(retVal); } } + /// /// /// A DecodedPointer allocated on Rust side. /// - public DecodedPointer? GetPointerButmap() + public DecodedPointer GetPointerBitmap() { unsafe { @@ -172,19 +179,21 @@ public ActiveStageOutputType GetType() { throw new ObjectDisposedException("ActiveStageOutput"); } - Raw.DecodedPointer* retVal = Raw.ActiveStageOutput.GetPointerButmap(_inner); - if (retVal == null) + Raw.SessionFfiResultBoxDecodedPointerBoxIronRdpError result = Raw.ActiveStageOutput.GetPointerBitmap(_inner); + if (!result.isOk) { - return null; + throw new IronRdpException(new IronRdpError(result.Err)); } + Raw.DecodedPointer* retVal = result.Ok; return new DecodedPointer(retVal); } } + /// /// /// A GracefulDisconnectReason allocated on Rust side. /// - public GracefulDisconnectReason? GetTerminate() + public GracefulDisconnectReason GetTerminate() { unsafe { @@ -192,19 +201,21 @@ public ActiveStageOutputType GetType() { throw new ObjectDisposedException("ActiveStageOutput"); } - Raw.GracefulDisconnectReason* retVal = Raw.ActiveStageOutput.GetTerminate(_inner); - if (retVal == null) + Raw.SessionFfiResultBoxGracefulDisconnectReasonBoxIronRdpError result = Raw.ActiveStageOutput.GetTerminate(_inner); + if (!result.isOk) { - return null; + throw new IronRdpException(new IronRdpError(result.Err)); } + Raw.GracefulDisconnectReason* retVal = result.Ok; return new GracefulDisconnectReason(retVal); } } + /// /// /// A ConnectionActivationSequence allocated on Rust side. /// - public ConnectionActivationSequence? GetDeactivateAll() + public ConnectionActivationSequence GetDeactivateAll() { unsafe { @@ -212,11 +223,12 @@ public ActiveStageOutputType GetType() { throw new ObjectDisposedException("ActiveStageOutput"); } - Raw.ConnectionActivationSequence* retVal = Raw.ActiveStageOutput.GetDeactivateAll(_inner); - if (retVal == null) + Raw.SessionFfiResultBoxConnectionActivationSequenceBoxIronRdpError result = Raw.ActiveStageOutput.GetDeactivateAll(_inner); + if (!result.isOk) { - return null; + throw new IronRdpException(new IronRdpError(result.Err)); } + Raw.ConnectionActivationSequence* retVal = result.Ok; return new ConnectionActivationSequence(retVal); } } diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/ClientConnector.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/ClientConnector.cs index dc594ae54..bcb08f4c0 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/ClientConnector.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/ClientConnector.cs @@ -15,7 +15,7 @@ public partial class ClientConnector: IDisposable { private unsafe Raw.ClientConnector* _inner; - public DynClientConnectorState DynState + public DynState DynState { get { @@ -285,9 +285,9 @@ public PduHint NextPduHint() /// /// - /// A DynClientConnectorState allocated on Rust side. + /// A DynState allocated on Rust side. /// - public DynClientConnectorState GetDynState() + public DynState GetDynState() { unsafe { @@ -295,13 +295,13 @@ public DynClientConnectorState GetDynState() { throw new ObjectDisposedException("ClientConnector"); } - Raw.ConnectorFfiResultBoxDynClientConnectorStateBoxIronRdpError result = Raw.ClientConnector.GetDynState(_inner); + Raw.ConnectorFfiResultBoxDynStateBoxIronRdpError result = Raw.ClientConnector.GetDynState(_inner); if (!result.isOk) { throw new IronRdpException(new IronRdpError(result.Err)); } - Raw.DynClientConnectorState* retVal = result.Ok; - return new DynClientConnectorState(retVal); + Raw.DynState* retVal = result.Ok; + return new DynState(retVal); } } @@ -309,7 +309,7 @@ public DynClientConnectorState GetDynState() /// /// A ClientConnectorState allocated on Rust side. /// - public ClientConnectorState ConsumeSelfAndGetState() + public ClientConnectorState ConsumeAndCastToClientConnectorState() { unsafe { @@ -317,7 +317,7 @@ public ClientConnectorState ConsumeSelfAndGetState() { throw new ObjectDisposedException("ClientConnector"); } - Raw.ConnectorFfiResultBoxClientConnectorStateBoxIronRdpError result = Raw.ClientConnector.ConsumeSelfAndGetState(_inner); + Raw.ConnectorFfiResultBoxClientConnectorStateBoxIronRdpError result = Raw.ClientConnector.ConsumeAndCastToClientConnectorState(_inner); if (!result.isOk) { throw new IronRdpException(new IronRdpError(result.Err)); diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/DynClientConnectorState.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/DynState.cs similarity index 73% rename from ffi/dotnet/Devolutions.IronRdp/Generated/DynClientConnectorState.cs rename to ffi/dotnet/Devolutions.IronRdp/Generated/DynState.cs index 447266b1d..ac9c42fd7 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/DynClientConnectorState.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/DynState.cs @@ -11,9 +11,9 @@ namespace Devolutions.IronRdp; #nullable enable -public partial class DynClientConnectorState: IDisposable +public partial class DynState: IDisposable { - private unsafe Raw.DynClientConnectorState* _inner; + private unsafe Raw.DynState* _inner; public string Name { @@ -24,7 +24,7 @@ public string Name } /// - /// Creates a managed DynClientConnectorState from a raw handle. + /// Creates a managed DynState from a raw handle. /// /// /// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free). @@ -32,7 +32,7 @@ public string Name /// This constructor assumes the raw struct is allocated on Rust side. /// If implemented, the custom Drop implementation on Rust side WILL run on destruction. /// - public unsafe DynClientConnectorState(Raw.DynClientConnectorState* handle) + public unsafe DynState(Raw.DynState* handle) { _inner = handle; } @@ -44,9 +44,9 @@ public void GetName(DiplomatWriteable writeable) { if (_inner == null) { - throw new ObjectDisposedException("DynClientConnectorState"); + throw new ObjectDisposedException("DynState"); } - Raw.ConnectorFfiResultVoidBoxIronRdpError result = Raw.DynClientConnectorState.GetName(_inner, &writeable); + Raw.ConnectorFfiResultVoidBoxIronRdpError result = Raw.DynState.GetName(_inner, &writeable); if (!result.isOk) { throw new IronRdpException(new IronRdpError(result.Err)); @@ -61,10 +61,10 @@ public string GetName() { if (_inner == null) { - throw new ObjectDisposedException("DynClientConnectorState"); + throw new ObjectDisposedException("DynState"); } DiplomatWriteable writeable = new DiplomatWriteable(); - Raw.ConnectorFfiResultVoidBoxIronRdpError result = Raw.DynClientConnectorState.GetName(_inner, &writeable); + Raw.ConnectorFfiResultVoidBoxIronRdpError result = Raw.DynState.GetName(_inner, &writeable); if (!result.isOk) { throw new IronRdpException(new IronRdpError(result.Err)); @@ -81,9 +81,9 @@ public bool IsTerminal() { if (_inner == null) { - throw new ObjectDisposedException("DynClientConnectorState"); + throw new ObjectDisposedException("DynState"); } - bool retVal = Raw.DynClientConnectorState.IsTerminal(_inner); + bool retVal = Raw.DynState.IsTerminal(_inner); return retVal; } } @@ -91,7 +91,7 @@ public bool IsTerminal() /// /// Returns the underlying raw handle. /// - public unsafe Raw.DynClientConnectorState* AsFFI() + public unsafe Raw.DynState* AsFFI() { return _inner; } @@ -108,14 +108,14 @@ public void Dispose() return; } - Raw.DynClientConnectorState.Destroy(_inner); + Raw.DynState.Destroy(_inner); _inner = null; GC.SuppressFinalize(this); } } - ~DynClientConnectorState() + ~DynState() { Dispose(); } diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/Database.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/InputDatabase.cs similarity index 69% rename from ffi/dotnet/Devolutions.IronRdp/Generated/Database.cs rename to ffi/dotnet/Devolutions.IronRdp/Generated/InputDatabase.cs index d3e15374a..fc59c3da7 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/Database.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/InputDatabase.cs @@ -11,12 +11,12 @@ namespace Devolutions.IronRdp; #nullable enable -public partial class Database: IDisposable +public partial class InputDatabase: IDisposable { - private unsafe Raw.Database* _inner; + private unsafe Raw.InputDatabase* _inner; /// - /// Creates a managed Database from a raw handle. + /// Creates a managed InputDatabase from a raw handle. /// /// /// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free). @@ -24,27 +24,27 @@ public partial class Database: IDisposable /// This constructor assumes the raw struct is allocated on Rust side. /// If implemented, the custom Drop implementation on Rust side WILL run on destruction. /// - public unsafe Database(Raw.Database* handle) + public unsafe InputDatabase(Raw.InputDatabase* handle) { _inner = handle; } /// - /// A Database allocated on Rust side. + /// A InputDatabase allocated on Rust side. /// - public static Database New() + public static InputDatabase New() { unsafe { - Raw.Database* retVal = Raw.Database.New(); - return new Database(retVal); + Raw.InputDatabase* retVal = Raw.InputDatabase.New(); + return new InputDatabase(retVal); } } /// /// Returns the underlying raw handle. /// - public unsafe Raw.Database* AsFFI() + public unsafe Raw.InputDatabase* AsFFI() { return _inner; } @@ -61,14 +61,14 @@ public void Dispose() return; } - Raw.Database.Destroy(_inner); + Raw.InputDatabase.Destroy(_inner); _inner = null; GC.SuppressFinalize(this); } } - ~Database() + ~InputDatabase() { Dispose(); } diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/IronRdpErrorKind.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/IronRdpErrorKind.cs index 029758eac..2b20bdacc 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/IronRdpErrorKind.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/IronRdpErrorKind.cs @@ -19,4 +19,5 @@ public enum IronRdpErrorKind Consumed = 3, IO = 4, AccessDenied = 5, + IncorrectEnumType = 6, } diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/Position.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/Position.cs index 7e8f6d860..e7bc1a896 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/Position.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/Position.cs @@ -11,95 +11,59 @@ namespace Devolutions.IronRdp; #nullable enable -public partial class Position: IDisposable +public partial class Position { - private unsafe Raw.Position* _inner; + private Raw.Position _inner; public ushort X { get { - return GetX(); + unsafe + { + return _inner.x; + } } - } - - public ushort Y - { - get + set { - return GetY(); + unsafe + { + _inner.x = value; + } } } - /// - /// Creates a managed Position from a raw handle. - /// - /// - /// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free). - ///
- /// This constructor assumes the raw struct is allocated on Rust side. - /// If implemented, the custom Drop implementation on Rust side WILL run on destruction. - ///
- public unsafe Position(Raw.Position* handle) - { - _inner = handle; - } - - public ushort GetX() + public ushort Y { - unsafe + get { - if (_inner == null) + unsafe { - throw new ObjectDisposedException("Position"); + return _inner.y; } - ushort retVal = Raw.Position.GetX(_inner); - return retVal; } - } - - public ushort GetY() - { - unsafe + set { - if (_inner == null) + unsafe { - throw new ObjectDisposedException("Position"); + _inner.y = value; } - ushort retVal = Raw.Position.GetY(_inner); - return retVal; } } /// - /// Returns the underlying raw handle. + /// Creates a managed Position from the raw representation. /// - public unsafe Raw.Position* AsFFI() + public unsafe Position(Raw.Position data) { - return _inner; + _inner = data; } /// - /// Destroys the underlying object immediately. + /// Returns a copy of the underlying raw representation. /// - public void Dispose() + public Raw.Position AsFFI() { - unsafe - { - if (_inner == null) - { - return; - } - - Raw.Position.Destroy(_inner); - _inner = null; - - GC.SuppressFinalize(this); - } - } - - ~Position() - { - Dispose(); + return _inner; } } diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStageOutput.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStageOutput.cs index 02a6d42e0..5aa25a44a 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStageOutput.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawActiveStageOutput.cs @@ -20,22 +20,22 @@ public partial struct ActiveStageOutput public static unsafe extern ActiveStageOutputType GetType(ActiveStageOutput* self); [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStageOutput_get_response_frame", ExactSpelling = true)] - public static unsafe extern BytesSlice* GetResponseFrame(ActiveStageOutput* self); + public static unsafe extern SessionFfiResultBoxBytesSliceBoxIronRdpError GetResponseFrame(ActiveStageOutput* self); [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStageOutput_get_graphics_update", ExactSpelling = true)] - public static unsafe extern InclusiveRectangle* GetGraphicsUpdate(ActiveStageOutput* self); + public static unsafe extern SessionFfiResultBoxInclusiveRectangleBoxIronRdpError GetGraphicsUpdate(ActiveStageOutput* self); [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStageOutput_get_pointer_position", ExactSpelling = true)] - public static unsafe extern Position* GetPointerPosition(ActiveStageOutput* self); + public static unsafe extern SessionFfiResultPositionBoxIronRdpError GetPointerPosition(ActiveStageOutput* self); - [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStageOutput_get_pointer_butmap", ExactSpelling = true)] - public static unsafe extern DecodedPointer* GetPointerButmap(ActiveStageOutput* self); + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStageOutput_get_pointer_bitmap", ExactSpelling = true)] + public static unsafe extern SessionFfiResultBoxDecodedPointerBoxIronRdpError GetPointerBitmap(ActiveStageOutput* self); [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStageOutput_get_terminate", ExactSpelling = true)] - public static unsafe extern GracefulDisconnectReason* GetTerminate(ActiveStageOutput* self); + public static unsafe extern SessionFfiResultBoxGracefulDisconnectReasonBoxIronRdpError GetTerminate(ActiveStageOutput* self); [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStageOutput_get_deactivate_all", ExactSpelling = true)] - public static unsafe extern ConnectionActivationSequence* GetDeactivateAll(ActiveStageOutput* self); + public static unsafe extern SessionFfiResultBoxConnectionActivationSequenceBoxIronRdpError GetDeactivateAll(ActiveStageOutput* self); [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStageOutput_destroy", ExactSpelling = true)] public static unsafe extern void Destroy(ActiveStageOutput* self); diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawClientConnector.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawClientConnector.cs index aa99c056f..ee4a24452 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/RawClientConnector.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawClientConnector.cs @@ -59,10 +59,10 @@ public partial struct ClientConnector public static unsafe extern ConnectorFfiResultOptBoxPduHintBoxIronRdpError NextPduHint(ClientConnector* self); [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnector_get_dyn_state", ExactSpelling = true)] - public static unsafe extern ConnectorFfiResultBoxDynClientConnectorStateBoxIronRdpError GetDynState(ClientConnector* self); + public static unsafe extern ConnectorFfiResultBoxDynStateBoxIronRdpError GetDynState(ClientConnector* self); - [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnector_consume_self_and_get_state", ExactSpelling = true)] - public static unsafe extern ConnectorFfiResultBoxClientConnectorStateBoxIronRdpError ConsumeSelfAndGetState(ClientConnector* self); + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnector_consume_and_cast_to_client_connector_state", ExactSpelling = true)] + public static unsafe extern ConnectorFfiResultBoxClientConnectorStateBoxIronRdpError ConsumeAndCastToClientConnectorState(ClientConnector* self); [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnector_destroy", ExactSpelling = true)] public static unsafe extern void Destroy(ClientConnector* self); diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoxDynClientConnectorStateBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoxDynStateBoxIronRdpError.cs similarity index 80% rename from ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoxDynClientConnectorStateBoxIronRdpError.cs rename to ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoxDynStateBoxIronRdpError.cs index 285db24d9..68b410941 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoxDynClientConnectorStateBoxIronRdpError.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoxDynStateBoxIronRdpError.cs @@ -12,13 +12,13 @@ namespace Devolutions.IronRdp.Raw; #nullable enable [StructLayout(LayoutKind.Sequential)] -public partial struct ConnectorFfiResultBoxDynClientConnectorStateBoxIronRdpError +public partial struct ConnectorFfiResultBoxDynStateBoxIronRdpError { [StructLayout(LayoutKind.Explicit)] private unsafe struct InnerUnion { [FieldOffset(0)] - internal DynClientConnectorState* ok; + internal DynState* ok; [FieldOffset(0)] internal IronRdpError* err; } @@ -28,7 +28,7 @@ private unsafe struct InnerUnion [MarshalAs(UnmanagedType.U1)] public bool isOk; - public unsafe DynClientConnectorState* Ok + public unsafe DynState* Ok { get { diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawDynClientConnectorState.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawDynState.cs similarity index 55% rename from ffi/dotnet/Devolutions.IronRdp/Generated/RawDynClientConnectorState.cs rename to ffi/dotnet/Devolutions.IronRdp/Generated/RawDynState.cs index c9dde4dae..9c1147ef2 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/RawDynClientConnectorState.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawDynState.cs @@ -12,17 +12,17 @@ namespace Devolutions.IronRdp.Raw; #nullable enable [StructLayout(LayoutKind.Sequential)] -public partial struct DynClientConnectorState +public partial struct DynState { private const string NativeLib = "DevolutionsIronRdp"; - [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DynClientConnectorState_get_name", ExactSpelling = true)] - public static unsafe extern ConnectorFfiResultVoidBoxIronRdpError GetName(DynClientConnectorState* self, DiplomatWriteable* writeable); + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DynState_get_name", ExactSpelling = true)] + public static unsafe extern ConnectorFfiResultVoidBoxIronRdpError GetName(DynState* self, DiplomatWriteable* writeable); - [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DynClientConnectorState_is_terminal", ExactSpelling = true)] + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DynState_is_terminal", ExactSpelling = true)] [return: MarshalAs(UnmanagedType.U1)] - public static unsafe extern bool IsTerminal(DynClientConnectorState* self); + public static unsafe extern bool IsTerminal(DynState* self); - [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DynClientConnectorState_destroy", ExactSpelling = true)] - public static unsafe extern void Destroy(DynClientConnectorState* self); + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DynState_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(DynState* self); } diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawDatabase.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawInputDatabase.cs similarity index 61% rename from ffi/dotnet/Devolutions.IronRdp/Generated/RawDatabase.cs rename to ffi/dotnet/Devolutions.IronRdp/Generated/RawInputDatabase.cs index 2403c70b5..b1699ddec 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/RawDatabase.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawInputDatabase.cs @@ -12,13 +12,13 @@ namespace Devolutions.IronRdp.Raw; #nullable enable [StructLayout(LayoutKind.Sequential)] -public partial struct Database +public partial struct InputDatabase { private const string NativeLib = "DevolutionsIronRdp"; - [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Database_new", ExactSpelling = true)] - public static unsafe extern Database* New(); + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "InputDatabase_new", ExactSpelling = true)] + public static unsafe extern InputDatabase* New(); - [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Database_destroy", ExactSpelling = true)] - public static unsafe extern void Destroy(Database* self); + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "InputDatabase_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(InputDatabase* self); } diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawIronRdpErrorKind.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawIronRdpErrorKind.cs index 83c1d0e1b..045a9aedf 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/RawIronRdpErrorKind.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawIronRdpErrorKind.cs @@ -19,4 +19,5 @@ public enum IronRdpErrorKind Consumed = 3, IO = 4, AccessDenied = 5, + IncorrectEnumType = 6, } diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawPosition.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawPosition.cs index b3ed2ce02..3c55209cf 100644 --- a/ffi/dotnet/Devolutions.IronRdp/Generated/RawPosition.cs +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawPosition.cs @@ -16,12 +16,7 @@ public partial struct Position { private const string NativeLib = "DevolutionsIronRdp"; - [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Position_get_x", ExactSpelling = true)] - public static unsafe extern ushort GetX(Position* self); + public ushort x; - [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Position_get_y", ExactSpelling = true)] - public static unsafe extern ushort GetY(Position* self); - - [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Position_destroy", ExactSpelling = true)] - public static unsafe extern void Destroy(Position* self); + public ushort y; } diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxBytesSliceBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxBytesSliceBoxIronRdpError.cs new file mode 100644 index 000000000..24821d13b --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxBytesSliceBoxIronRdpError.cs @@ -0,0 +1,46 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct SessionFfiResultBoxBytesSliceBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal BytesSlice* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe BytesSlice* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxConnectionActivationSequenceBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxConnectionActivationSequenceBoxIronRdpError.cs new file mode 100644 index 000000000..0095580e4 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxConnectionActivationSequenceBoxIronRdpError.cs @@ -0,0 +1,46 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct SessionFfiResultBoxConnectionActivationSequenceBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal ConnectionActivationSequence* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe ConnectionActivationSequence* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxDecodedPointerBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxDecodedPointerBoxIronRdpError.cs new file mode 100644 index 000000000..dc819759c --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxDecodedPointerBoxIronRdpError.cs @@ -0,0 +1,46 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct SessionFfiResultBoxDecodedPointerBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal DecodedPointer* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe DecodedPointer* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxGracefulDisconnectReasonBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxGracefulDisconnectReasonBoxIronRdpError.cs new file mode 100644 index 000000000..23d2076c0 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxGracefulDisconnectReasonBoxIronRdpError.cs @@ -0,0 +1,46 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct SessionFfiResultBoxGracefulDisconnectReasonBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal GracefulDisconnectReason* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe GracefulDisconnectReason* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxInclusiveRectangleBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxInclusiveRectangleBoxIronRdpError.cs new file mode 100644 index 000000000..7b9a9b0d5 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultBoxInclusiveRectangleBoxIronRdpError.cs @@ -0,0 +1,46 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct SessionFfiResultBoxInclusiveRectangleBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal InclusiveRectangle* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe InclusiveRectangle* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultPositionBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultPositionBoxIronRdpError.cs new file mode 100644 index 000000000..ac73edc65 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawSessionFfiResultPositionBoxIronRdpError.cs @@ -0,0 +1,46 @@ +// by Diplomat + +#pragma warning disable 0105 +using System; +using System.Runtime.InteropServices; + +using Devolutions.IronRdp.Diplomat; +#pragma warning restore 0105 + +namespace Devolutions.IronRdp.Raw; + +#nullable enable + +[StructLayout(LayoutKind.Sequential)] +public partial struct SessionFfiResultPositionBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal Position ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe Position Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/src/Connection.cs b/ffi/dotnet/Devolutions.IronRdp/src/Connection.cs index ea8519d07..48086ee47 100644 --- a/ffi/dotnet/Devolutions.IronRdp/src/Connection.cs +++ b/ffi/dotnet/Devolutions.IronRdp/src/Connection.cs @@ -71,7 +71,7 @@ private static async Task ConnectFinalize(string servername, C await SingleConnectStep(connector, writeBuf2, framedSsl); } - ClientConnectorState state = connector.ConsumeSelfAndGetState(); + ClientConnectorState state = connector.ConsumeAndCastToClientConnectorState(); if (state.GetType() == ClientConnectorStateType.Connected) { @@ -125,7 +125,7 @@ private static async Task PerformCredsspSteps(ClientConnector connector, string private static async Task ResolveGenerator(CredsspProcessGenerator generator, TcpClient tcpClient) { var state = generator.Start(); - NetworkStream stream = null; + NetworkStream? stream = null; while (true) { if (state.IsSuspended()) diff --git a/ffi/src/connector/config.rs b/ffi/src/connector/config.rs index e70f30066..d150cdfea 100644 --- a/ffi/src/connector/config.rs +++ b/ffi/src/connector/config.rs @@ -148,7 +148,7 @@ pub mod ffi { pub fn build(&self) -> Result, Box> { let inner_config = ironrdp::connector::Config { - credentials: self.credentials.clone().ok_or("Credentials not set")?, + credentials: self.credentials.clone().ok_or("credentials not set")?, domain: self.domain.clone(), enable_tls: self.enable_tls.unwrap_or(false), enable_credssp: self.enable_credssp.unwrap_or(true), @@ -160,11 +160,11 @@ pub mod ffi { keyboard_functional_keys_count: self.keyboard_functional_keys_count.unwrap_or(12), ime_file_name: self.ime_file_name.clone().unwrap_or_default(), dig_product_id: self.dig_product_id.clone().unwrap_or_default(), - desktop_size: self.desktop_size.ok_or("Desktop size not set")?, + desktop_size: self.desktop_size.ok_or("desktop size not set")?, bitmap: None, client_build: self.client_build.unwrap_or(0), - client_name: self.client_name.clone().ok_or("Client name not set")?, - client_dir: self.client_dir.clone().ok_or("Client dir not set")?, + client_name: self.client_name.clone().ok_or("client name not set")?, + client_dir: self.client_dir.clone().ok_or("client dir not set")?, #[cfg(windows)] platform: MajorPlatformType::WINDOWS, @@ -188,7 +188,7 @@ pub mod ffi { no_server_pointer: self.no_server_pointer.unwrap_or(false), autologon: self.autologon.unwrap_or(false), pointer_software_rendering: self.pointer_software_rendering.unwrap_or(false), - performance_flags: self.performance_flags.ok_or("Performance flag is missing")?, + performance_flags: self.performance_flags.ok_or("performance flag is missing")?, }; Ok(Box::new(Config(inner_config))) diff --git a/ffi/src/connector/mod.rs b/ffi/src/connector/mod.rs index a793dacfb..6b764133b 100644 --- a/ffi/src/connector/mod.rs +++ b/ffi/src/connector/mod.rs @@ -132,9 +132,9 @@ pub mod ffi { } #[diplomat::opaque] - pub struct DynClientConnectorState<'a>(pub &'a dyn ironrdp::connector::State); + pub struct DynState<'a>(pub &'a dyn ironrdp::connector::State); - impl<'a> DynClientConnectorState<'a> { + impl<'a> DynState<'a> { pub fn get_name(&'a self, writeable: &'a mut DiplomatWriteable) -> Result<(), Box> { let name = self.0.name(); write!(writeable, "{}", name)?; @@ -154,14 +154,16 @@ pub mod ffi { Ok(connector.next_pdu_hint().map(PduHint).map(Box::new)) } - pub fn get_dyn_state(&self) -> Result>, Box> { + pub fn get_dyn_state(&self) -> Result>, Box> { let Some(connector) = self.0.as_ref() else { return Err(ValueConsumedError::for_item("connector").into()); }; - Ok(Box::new(DynClientConnectorState(connector.state()))) + Ok(Box::new(DynState(connector.state()))) } - pub fn consume_and_cast_to_client_connector_state(&mut self) -> Result, Box> { + pub fn consume_and_cast_to_client_connector_state( + &mut self, + ) -> Result, Box> { let Some(connector) = self.0.take() else { return Err(ValueConsumedError::for_item("connector").into()); }; diff --git a/ffi/src/connector/state.rs b/ffi/src/connector/state.rs index 9241d9634..2a9519ae2 100644 --- a/ffi/src/connector/state.rs +++ b/ffi/src/connector/state.rs @@ -1,7 +1,7 @@ #[diplomat::bridge] pub mod ffi { use crate::{ - error::{ffi::IronRdpError, ValueConsumedError}, + error::{ffi::IronRdpError, IncorrectEnumTypeError, ValueConsumedError}, pdu::ffi::SecurityProtocol, }; @@ -89,7 +89,9 @@ pub mod ffi { ironrdp::connector::ClientConnectorState::ConnectionInitiationWaitConfirm { requested_protocol } => { Ok(SecurityProtocol(requested_protocol)) } - _ => Err("not in ConnectionInitiationWaitConfirm state".into()), + _ => Err(IncorrectEnumTypeError::on_variant("ConnectionInitiationWaitConfirm") + .of_enum("ClientConnectorState") + .into()), } .map(Box::new) } @@ -105,7 +107,9 @@ pub mod ffi { ironrdp::connector::ClientConnectorState::EnhancedSecurityUpgrade { selected_protocol } => { Ok(SecurityProtocol(selected_protocol)) } - _ => Err("Not in EnhancedSecurityUpgrade state".into()), + _ => Err(IncorrectEnumTypeError::on_variant("EnhancedSecurityUpgrade") + .of_enum("ClientConnectorState") + .into()), } .map(Box::new) } @@ -119,7 +123,9 @@ pub mod ffi { ironrdp::connector::ClientConnectorState::Credssp { selected_protocol } => { Ok(SecurityProtocol(selected_protocol)) } - _ => Err("Not in Credssp state".into()), + _ => Err(IncorrectEnumTypeError::on_variant("Credssp") + .of_enum("ClientConnectorState") + .into()), } .map(Box::new) } @@ -135,7 +141,9 @@ pub mod ffi { ironrdp::connector::ClientConnectorState::BasicSettingsExchangeSendInitial { selected_protocol } => { Ok(SecurityProtocol(selected_protocol)) } - _ => Err("Not in BasicSettingsExchangeSendInitial state".into()), + _ => Err(IncorrectEnumTypeError::on_variant("BasicSettingsExchangeSendInitial") + .of_enum("ClientConnectorState") + .into()), } .map(Box::new) } @@ -151,7 +159,9 @@ pub mod ffi { ironrdp::connector::ClientConnectorState::BasicSettingsExchangeWaitResponse { connect_initial } => { Ok(crate::pdu::ffi::ConnectInitial(connect_initial)) } - _ => Err("Not in BasicSettingsExchangeWaitResponse state".into()), + _ => Err(IncorrectEnumTypeError::on_variant("BasicSettingsExchangeWaitResponse") + .of_enum("ClientConnectorState") + .into()), } .map(Box::new) } @@ -169,7 +179,9 @@ pub mod ffi { ironrdp::connector::ClientConnectorState::Connected { result } => { Ok(Box::new(crate::connector::result::ffi::ConnectionResult(Some(result)))) } - _ => Err("Not in Connected state".into()), + _ => Err(IncorrectEnumTypeError::on_variant("Connected") + .of_enum("ClientConnectorState") + .into()), } } } diff --git a/ffi/src/error.rs b/ffi/src/error.rs index 9b6365b56..05e26c830 100644 --- a/ffi/src/error.rs +++ b/ffi/src/error.rs @@ -90,6 +90,8 @@ pub mod ffi { IO, #[error("Access denied")] AccessDenied, + #[error("Incorrect rust enum type")] + IncorrectEnumType, } /// Stringified Picky error along with an error kind. @@ -145,3 +147,43 @@ impl From for IronRdpErrorKind { IronRdpErrorKind::Consumed } } + +pub struct IncorrectEnumTypeError { + expected: &'static str, + enum_name: &'static str, +} + +impl IncorrectEnumTypeError { + pub fn on_variant(variant: &'static str) -> IncorrectEnumTypeErrorBuilder { + IncorrectEnumTypeErrorBuilder { expected: variant } + } +} + +pub struct IncorrectEnumTypeErrorBuilder { + expected: &'static str, +} + +impl IncorrectEnumTypeErrorBuilder { + pub fn of_enum(self, enum_name: &'static str) -> IncorrectEnumTypeError { + IncorrectEnumTypeError { + expected: self.expected, + enum_name, + } + } +} + +impl Display for IncorrectEnumTypeError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "expected enum variable {}, of enum {}", + self.expected, self.enum_name + ) + } +} + +impl From for IronRdpErrorKind { + fn from(_val: IncorrectEnumTypeError) -> Self { + IronRdpErrorKind::IncorrectEnumType + } +} diff --git a/ffi/src/input.rs b/ffi/src/input.rs index 0e5b6ee39..ca7eba7aa 100644 --- a/ffi/src/input.rs +++ b/ffi/src/input.rs @@ -1,11 +1,11 @@ #[diplomat::bridge] pub mod ffi { #[diplomat::opaque] - pub struct Database(pub ironrdp::input::Database); + pub struct InputDatabase(pub ironrdp::input::Database); - impl Database { - pub fn new() -> Box { - Box::new(Database(ironrdp::input::Database::new())) + impl InputDatabase { + pub fn new() -> Box { + Box::new(InputDatabase(ironrdp::input::Database::new())) } } } diff --git a/ffi/src/lib.rs b/ffi/src/lib.rs index 4ae79f542..d16ead910 100644 --- a/ffi/src/lib.rs +++ b/ffi/src/lib.rs @@ -1,4 +1,5 @@ #![allow(clippy::unnecessary_box_returns)] // Diplomat requires returning Boxed types +#![allow(clippy::should_implement_trait)] // Implementing extra traits is not useful for FFI pub mod connector; pub mod credssp; diff --git a/ffi/src/session/mod.rs b/ffi/src/session/mod.rs index b7c9f3908..1ba65faae 100644 --- a/ffi/src/session/mod.rs +++ b/ffi/src/session/mod.rs @@ -1,4 +1,3 @@ -#![allow(clippy::should_implement_trait)] // Implementing extra traits is not useful for FFI pub mod image; #[diplomat::bridge] @@ -6,7 +5,7 @@ pub mod ffi { use crate::{ connector::{ffi::ConnectionActivationSequence, result::ffi::ConnectionResult}, - error::{ffi::IronRdpError, ValueConsumedError}, + error::{ffi::IronRdpError, IncorrectEnumTypeError, ValueConsumedError}, graphics::ffi::DecodedPointer, pdu::ffi::{Action, InclusiveRectangle}, utils::ffi::{BytesSlice, Position}, @@ -83,54 +82,65 @@ pub mod ffi { } } - pub fn get_response_frame(&self) -> Option>> { + pub fn get_response_frame(&self) -> Result>, Box> { match &self.0 { - ironrdp::session::ActiveStageOutput::ResponseFrame(frame) => Some(Box::new(BytesSlice(frame))), - _ => None, + ironrdp::session::ActiveStageOutput::ResponseFrame(frame) => Ok(Box::new(BytesSlice(frame))), + _ => Err(IncorrectEnumTypeError::on_variant("ResponseFrame") + .of_enum("ActiveStageOutput") + .into()), } } - pub fn get_graphics_update(&self) -> Option> { + pub fn get_graphics_update(&self) -> Result, Box> { match &self.0 { ironrdp::session::ActiveStageOutput::GraphicsUpdate(rect) => { - Some(Box::new(InclusiveRectangle(rect.clone()))) + Ok(Box::new(InclusiveRectangle(rect.clone()))) } - _ => None, + _ => Err(IncorrectEnumTypeError::on_variant("GraphicsUpdate") + .of_enum("ActiveStageOutput") + .into()), } } - pub fn get_pointer_position(&self) -> Option> { + pub fn get_pointer_position(&self) -> Result> { match &self.0 { - ironrdp::session::ActiveStageOutput::PointerPosition { x, y } => Some(Position { x: *x, y: *y }), - _ => None, + ironrdp::session::ActiveStageOutput::PointerPosition { x, y } => Ok(Position { x: *x, y: *y }), + _ => Err(IncorrectEnumTypeError::on_variant("PointerPosition") + .of_enum("ActiveStageOutput") + .into()), } - .map(Box::new) } - pub fn get_pointer_bitmap(&self) -> Option> { + pub fn get_pointer_bitmap(&self) -> Result, Box> { match &self.0 { ironrdp::session::ActiveStageOutput::PointerBitmap(decoded_pointer) => { - Some(DecodedPointer(std::rc::Rc::clone(decoded_pointer))) + Ok(DecodedPointer(std::rc::Rc::clone(decoded_pointer))) } - _ => None, + _ => Err(IncorrectEnumTypeError::on_variant("PointerBitmap") + .of_enum("ActiveStageOutput") + .into()), } .map(Box::new) } - pub fn get_terminate(&self) -> Option> { + pub fn get_terminate(&self) -> Result, Box> { match &self.0 { - ironrdp::session::ActiveStageOutput::Terminate(reason) => Some(GracefulDisconnectReason(*reason)), - _ => None, + ironrdp::session::ActiveStageOutput::Terminate(reason) => Ok(GracefulDisconnectReason(*reason)), + _ => Err(IncorrectEnumTypeError::on_variant("Terminate") + .of_enum("ActiveStageOutput") + .into()), } .map(Box::new) } - pub fn get_deactivate_all(&self) -> Option> { + pub fn get_deactivate_all(&self) -> Result, Box> { match &self.0 { ironrdp::session::ActiveStageOutput::DeactivateAll(cas) => { - Some(ConnectionActivationSequence(cas.clone())) + Ok(ConnectionActivationSequence(cas.clone())) } - _ => None, + _ => Err(IncorrectEnumTypeError::on_variant("DeactivateAll") + .of_enum("ActiveStageOutput") + .into()), } .map(Box::new) } diff --git a/ffi/src/utils/mod.rs b/ffi/src/utils/mod.rs index 66bd58806..672c5653e 100644 --- a/ffi/src/utils/mod.rs +++ b/ffi/src/utils/mod.rs @@ -17,7 +17,7 @@ pub mod ffi { pub fn fill(&self, buffer: &mut [u8]) -> Result<(), Box> { if buffer.len() < self.0.len() { - return Err("Buffer is too small".into()); + return Err("buffer is too small".into()); } buffer.copy_from_slice(&self.0); Ok(()) @@ -38,7 +38,7 @@ pub mod ffi { pub fn fill(&'a self, buffer: &'a mut [u8]) -> Result<(), Box> { if buffer.len() < self.0.len() { - return Err("Buffer is too small".into()); + return Err("buffer is too small".into()); } buffer.copy_from_slice(self.0); Ok(()) @@ -55,29 +55,18 @@ pub mod ffi { pub fn fill(&'a self, buffer: &'a mut [u32]) -> Result<(), Box> { if buffer.len() < self.0.len() { - return Err("Buffer is too small".into()); + return Err("buffer is too small".into()); } buffer.copy_from_slice(self.0); Ok(()) } } - #[diplomat::opaque] pub struct Position { pub x: u16, pub y: u16, } - impl Position { - pub fn get_x(&self) -> u16 { - self.x - } - - pub fn get_y(&self) -> u16 { - self.y - } - } - #[diplomat::opaque] pub struct OptionalUsize(pub Option); @@ -87,7 +76,7 @@ pub mod ffi { } pub fn get(&self) -> Result> { - self.0.ok_or_else(|| "Value is None".into()) + self.0.ok_or_else(|| "value is None".into()) } } } From 463e368023b601457821c919ec8b62d192cd78f1 Mon Sep 17 00:00:00 2001 From: irving ou Date: Mon, 8 Apr 2024 20:41:21 -0400 Subject: [PATCH 16/18] Review fix:2 --- .../Devolutions.IronRdp.ConnectExample.csproj | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Devolutions.IronRdp.ConnectExample.csproj b/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Devolutions.IronRdp.ConnectExample.csproj index deef7a6dc..f261234a2 100644 --- a/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Devolutions.IronRdp.ConnectExample.csproj +++ b/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Devolutions.IronRdp.ConnectExample.csproj @@ -11,9 +11,4 @@ - - - - - From 4808c6f8c4526fb6a4bc0c48371814c064b997ed Mon Sep 17 00:00:00 2001 From: irving ou Date: Mon, 8 Apr 2024 20:46:17 -0400 Subject: [PATCH 17/18] Review fix:3 --- .../Devolutions.IronRdp.ConnectExample.csproj | 4 ++++ ffi/dotnet/Devolutions.IronRdp.ConnectExample/Program.cs | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Devolutions.IronRdp.ConnectExample.csproj b/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Devolutions.IronRdp.ConnectExample.csproj index f261234a2..166fc7428 100644 --- a/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Devolutions.IronRdp.ConnectExample.csproj +++ b/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Devolutions.IronRdp.ConnectExample.csproj @@ -11,4 +11,8 @@ + + + + diff --git a/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Program.cs b/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Program.cs index efcc4b997..4add02b48 100644 --- a/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Program.cs +++ b/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Program.cs @@ -1,6 +1,5 @@ using System.Drawing; using System.Drawing.Imaging; -using Devolutions.IronRdp; namespace Devolutions.IronRdp.ConnectExample { @@ -89,6 +88,7 @@ private static void saveImage(DecodedImage decodedImage, string v) bytes[i + 2] = temp; // Move original Blue to Red's position // Green (bytes[i+1]) and Alpha (bytes[i+3]) remain unchanged } + #if WINDOWS // Bitmap is only available on Windows using (var bmp = new Bitmap(width, height)) { // Lock the bits of the bitmap. @@ -105,7 +105,7 @@ private static void saveImage(DecodedImage decodedImage, string v) // Save the bitmap to the specified output path bmp.Save("./output.bmp", ImageFormat.Bmp); } - + #endif } @@ -118,7 +118,7 @@ private static void saveImage(DecodedImage decodedImage, string v) } var arguments = new Dictionary(); - string lastKey = null; + string? lastKey = null; foreach (var arg in args) { if (arg.StartsWith("--")) From 7e824c5b9bc3cf07ca1dc387a195de8c1b296e61 Mon Sep 17 00:00:00 2001 From: irving ou Date: Mon, 8 Apr 2024 20:53:11 -0400 Subject: [PATCH 18/18] Review fix:4 --- ffi/dotnet/Devolutions.IronRdp.ConnectExample/Program.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Program.cs b/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Program.cs index 4add02b48..7e9a7f855 100644 --- a/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Program.cs +++ b/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Program.cs @@ -39,8 +39,7 @@ static async Task Main(string[] args) else { Console.WriteLine("Timeout"); - keepLooping = false; - continue; + break; } var outputIterator = activeState.Process(decodedImage, action, payload);