diff --git a/.gitattribute b/.gitattribute new file mode 100644 index 000000000..abc994967 --- /dev/null +++ b/.gitattribute @@ -0,0 +1,8 @@ +*.rs text eol=lf +*.toml text eol=lf +*.cs text eol=lf +*.js text eol=lf +*.ps1 text eol=lf +*.sln text eol=crlf + +ffi/dotnet/Devolutions.IronRdp/Generated/** linguist-generated merge=binary \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index d3f9f463a..69b32ad17 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -776,9 +776,9 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "der" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", "der_derive", @@ -858,6 +858,39 @@ dependencies = [ "subtle", ] +[[package]] +name = "diplomat" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31672b3ebc3c7866c3c98726f7a9a5ac8f13962e77d3c8225f6be49a7b8c5f2" +dependencies = [ + "diplomat_core", + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "diplomat-runtime" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7b0f23d549a46540e26e5490cd44c64ced0d762959f1ffdec6ab0399634cf3c" + +[[package]] +name = "diplomat_core" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfaa5e13e8b8735d2338f2836c06cd8643902ab87dda1dd07dbb351998ddc127" +dependencies = [ + "lazy_static", + "proc-macro2", + "quote", + "serde", + "smallvec", + "strck_ident", + "syn 2.0.48", +] + [[package]] name = "dispatch" version = "0.2.0" @@ -1001,6 +1034,20 @@ dependencies = [ "zeroize", ] +[[package]] +name = "embed-resource" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6985554d0688b687c5cb73898a34fbe3ad6c24c58c238a4d91d5e840670ee9d" +dependencies = [ + "cc", + "memchr", + "rustc_version", + "toml", + "vswhom", + "winreg 0.52.0", +] + [[package]] name = "encoding_rs" version = "0.8.33" @@ -1073,6 +1120,18 @@ dependencies = [ "subtle", ] +[[package]] +name = "ffi" +version = "0.1.0" +dependencies = [ + "diplomat", + "diplomat-runtime", + "embed-resource", + "ironrdp", + "sspi", + "thiserror", +] + [[package]] name = "fiat-crypto" version = "0.2.5" @@ -1643,7 +1702,7 @@ dependencies = [ "pico-args", "rand", "rustls", - "rustls-pemfile 2.1.0", + "rustls-pemfile 2.1.1", "tokio", "tokio-rustls", "tracing", @@ -2951,7 +3010,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ "once_cell", - "toml_edit", + "toml_edit 0.19.15", ] [[package]] @@ -3344,9 +3403,9 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c333bb734fcdedcea57de1602543590f545f127dc8b533324318fd492c5c70b" +checksum = "f48172685e6ff52a556baa527774f61fcaa884f59daf3375c62a3f1cd2549dab" dependencies = [ "base64", "rustls-pki-types", @@ -3513,6 +3572,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -3764,6 +3832,22 @@ dependencies = [ "zeroize", ] +[[package]] +name = "strck" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be91090ded9d8f979d9fe921777342d37e769e0b6b7296843a7a38247240e917" + +[[package]] +name = "strck_ident" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1c3802b169b3858a44667f221c9a0b3136e6019936ea926fc97fbad8af77202" +dependencies = [ + "strck", + "unicode-ident", +] + [[package]] name = "strict-num" version = "0.1.1" @@ -4066,11 +4150,26 @@ dependencies = [ "tracing", ] +[[package]] +name = "toml" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.22.9", +] + [[package]] name = "toml_datetime" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +dependencies = [ + "serde", +] [[package]] name = "toml_edit" @@ -4080,7 +4179,20 @@ checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ "indexmap", "toml_datetime", - "winnow", + "winnow 0.5.34", +] + +[[package]] +name = "toml_edit" +version = "0.22.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow 0.6.5", ] [[package]] @@ -4325,6 +4437,26 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "vswhom" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be979b7f07507105799e854203b470ff7c78a1639e330a58f183b5fea574608b" +dependencies = [ + "libc", + "vswhom-sys", +] + +[[package]] +name = "vswhom-sys" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3b17ae1f6c8a2b28506cd96d412eebf83b4a0ff2cbefeeb952f2f9dfa44ba18" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "wait-timeout" version = "0.2.0" @@ -4879,6 +5011,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.50.0" @@ -4899,6 +5040,16 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "winreg" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "wyz" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index 9895d9bd4..1f358cf38 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ members = [ "crates/*", "xtask", + "ffi", ] resolver = "2" diff --git a/ffi/Cargo.toml b/ffi/Cargo.toml new file mode 100644 index 000000000..a38846d2b --- /dev/null +++ b/ffi/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "ffi" +version = "0.1.0" +edition.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true +authors.workspace = true +keywords.workspace = true +categories.workspace = true + +[lib] +name = "ironrdp" +crate-type = ["staticlib", "cdylib"] +doc = false +test = false +doctest = false + +[dependencies] +diplomat = "0.7.0" +diplomat-runtime = "0.7.0" +ironrdp = { workspace = true, features = ["connector", "dvc", "svc","rdpdr","rdpsnd"] } +sspi = { workspace = true, features = ["network_client"] } +thiserror.workspace = true + +[target.'cfg(windows)'.build-dependencies] +embed-resource = "2.2.0" diff --git a/ffi/build.rs b/ffi/build.rs new file mode 100644 index 000000000..9e13504fc --- /dev/null +++ b/ffi/build.rs @@ -0,0 +1,101 @@ +#[cfg(not(target_os = "windows"))] +use other::main_stub; +#[cfg(target_os = "windows")] +use win::main_stub; + +fn main() { + main_stub(); +} + +#[cfg(target_os = "windows")] +mod win { + extern crate embed_resource; + + use std::env; + use std::fs::File; + use std::io::Write; + + fn generate_version_rc() -> String { + let output_name = "DevolutionsIronRdp"; + let filename = format!("{}.dll", output_name); + let company_name = "Devolutions Inc."; + let legal_copyright = format!("Copyright 2019-2024 {}", company_name); + + let mut cargo_version = env::var("CARGO_PKG_VERSION").unwrap(); + cargo_version.push_str(".0"); + + let version_number = cargo_version; + let version_commas = version_number.replace('.', ","); + let file_description = output_name; + let file_version = version_number.clone(); + let internal_name = filename.clone(); + let original_filename = filename; + let product_name = output_name; + let product_version = version_number; + let vs_file_version = version_commas.clone(); + let vs_product_version = version_commas; + + let version_rc = format!( + r#"#include +VS_VERSION_INFO VERSIONINFO + FILEVERSION {vs_file_version} + PRODUCTVERSION {vs_product_version} + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "{company_name}" + VALUE "FileDescription", "{file_description}" + VALUE "FileVersion", "{file_version}" + VALUE "InternalName", "{internal_name}" + VALUE "LegalCopyright", "{legal_copyright}" + VALUE "OriginalFilename", "{original_filename}" + VALUE "ProductName", "{product_name}" + VALUE "ProductVersion", "{product_version}" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END +"#, + vs_file_version = vs_file_version, + vs_product_version = vs_product_version, + company_name = company_name, + file_description = file_description, + file_version = file_version, + internal_name = internal_name, + legal_copyright = legal_copyright, + original_filename = original_filename, + product_name = product_name, + product_version = product_version + ); + + version_rc + } + + pub(crate) fn main_stub() { + let out_dir = env::var("OUT_DIR").unwrap(); + let version_rc_file = format!("{}/version.rc", out_dir); + let version_rc_data = generate_version_rc(); + let mut file = File::create(&version_rc_file).expect("cannot create version.rc file"); + file.write_all(version_rc_data.as_bytes()).unwrap(); + embed_resource::compile(&version_rc_file, embed_resource::NONE); + } +} + +#[cfg(not(target_os = "windows"))] +mod other { + pub(crate) fn main_stub() {} +} diff --git a/ffi/dotnet-interop-conf.toml b/ffi/dotnet-interop-conf.toml new file mode 100644 index 000000000..e2c76a3af --- /dev/null +++ b/ffi/dotnet-interop-conf.toml @@ -0,0 +1,10 @@ +namespace = "Devolutions.IronRdp" +native_lib = "DevolutionsIronRdp" + +[exceptions] +trim_suffix = "Error" +error_message_method = "ToDisplay" + +[properties] +setters_prefix = "set_" +getters_prefix = "get_" diff --git a/ffi/dotnet/Devolutions.IronRdp.ConnectExample/.gitignore b/ffi/dotnet/Devolutions.IronRdp.ConnectExample/.gitignore new file mode 100644 index 000000000..501bb1289 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp.ConnectExample/.gitignore @@ -0,0 +1,3 @@ +obj +bin +.vs \ 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 new file mode 100644 index 000000000..2e1eeb1b9 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Devolutions.IronRdp.ConnectExample.csproj @@ -0,0 +1,14 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + diff --git a/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Program.cs b/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Program.cs new file mode 100644 index 000000000..d09ee3625 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Program.cs @@ -0,0 +1,318 @@ +using System.Net; +using System.Net.Security; +using System.Net.Sockets; + +namespace Devolutions.IronRdp.ConnectExample +{ + class Program + { + static async Task Main(string[] args) + { + var arguments = ParseArguments(args); + + if (arguments == null) + { + return; + } + + var serverName = arguments["--serverName"]; + var username = arguments["--username"]; + var password = arguments["--password"]; + var domain = arguments["--domain"]; + try + { + await Connect(serverName, username, password, domain); + } + catch (Exception e) + { + Console.WriteLine($"An error occurred: {e.Message}"); + } + } + + static Dictionary ParseArguments(string[] args) + { + if (args.Length == 0 || Array.Exists(args, arg => arg == "--help")) + { + PrintHelp(); + return null; + } + + var arguments = new Dictionary(); + string lastKey = null; + foreach (var arg in args) + { + if (arg.StartsWith("--")) + { + if (lastKey != null) + { + Console.WriteLine($"Error: Missing value for {lastKey}."); + PrintHelp(); + return null; + } + if (!IsValidArgument(arg)) + { + Console.WriteLine($"Error: Unknown argument {arg}."); + PrintHelp(); + return null; + } + lastKey = arg; + } + else + { + if (lastKey == null) + { + Console.WriteLine("Error: Value without a preceding flag."); + PrintHelp(); + return null; + } + arguments[lastKey] = arg; + lastKey = null; + } + } + + if (lastKey != null) + { + Console.WriteLine($"Error: Missing value for {lastKey}."); + PrintHelp(); + return null; + } + + return arguments; + } + + static bool IsValidArgument(string argument) + { + var validArguments = new List { "--serverName", "--username", "--password", "--domain" }; + return validArguments.Contains(argument); + } + + static void PrintHelp() + { + Console.WriteLine("Usage: dotnet run -- [OPTIONS]"); + Console.WriteLine("Options:"); + Console.WriteLine(" --serverName The name of the server to connect to."); + Console.WriteLine(" --username The username for connection."); + Console.WriteLine(" --password The password for connection."); + Console.WriteLine(" --domain The domain of the server."); + 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; + } + } +} + + diff --git a/ffi/dotnet/Devolutions.IronRdp/.gitignore b/ffi/dotnet/Devolutions.IronRdp/.gitignore new file mode 100644 index 000000000..2e9693ed1 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/.gitignore @@ -0,0 +1,2 @@ +obj +bin \ No newline at end of file diff --git a/ffi/dotnet/Devolutions.IronRdp/Devolutions.IronRdp.csproj b/ffi/dotnet/Devolutions.IronRdp/Devolutions.IronRdp.csproj new file mode 100644 index 000000000..bd44ee5ae --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Devolutions.IronRdp.csproj @@ -0,0 +1,10 @@ + + + + net8.0 + enable + enable + true + + + diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/ClientConnector.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/ClientConnector.cs new file mode 100644 index 000000000..b87c0fce1 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/ClientConnector.cs @@ -0,0 +1,331 @@ +// 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 ClientConnector: IDisposable +{ + private unsafe Raw.ClientConnector* _inner; + + /// + /// Creates a managed ClientConnector 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 ClientConnector(Raw.ClientConnector* handle) + { + _inner = handle; + } + + /// + /// A ClientConnector allocated on Rust side. + /// + public static ClientConnector New(Config config) + { + unsafe + { + Raw.Config* configRaw; + configRaw = config.AsFFI(); + if (configRaw == null) + { + throw new ObjectDisposedException("Config"); + } + Raw.ClientConnector* retVal = Raw.ClientConnector.New(configRaw); + return new ClientConnector(retVal); + } + } + + /// + /// Must use + /// + /// + public void WithServerAddr(string serverAddr) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ClientConnector"); + } + byte[] serverAddrBuf = DiplomatUtils.StringToUtf8(serverAddr); + nuint serverAddrBufLength = (nuint)serverAddrBuf.Length; + fixed (byte* serverAddrBufPtr = serverAddrBuf) + { + Raw.ConnectorFfiResultVoidBoxIronRdpError result = Raw.ClientConnector.WithServerAddr(_inner, serverAddrBufPtr, serverAddrBufLength); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + } + } + } + + /// + /// Must use + /// + /// + public void WithStaticChannelRdpSnd() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ClientConnector"); + } + Raw.ConnectorFfiResultVoidBoxIronRdpError result = Raw.ClientConnector.WithStaticChannelRdpSnd(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + } + } + + /// + /// Must use + /// + /// + public void WithStaticChannelRdpdr(string computerName, uint smartCardDeviceId) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ClientConnector"); + } + byte[] computerNameBuf = DiplomatUtils.StringToUtf8(computerName); + nuint computerNameBufLength = (nuint)computerNameBuf.Length; + fixed (byte* computerNameBufPtr = computerNameBuf) + { + Raw.ConnectorFfiResultVoidBoxIronRdpError result = Raw.ClientConnector.WithStaticChannelRdpdr(_inner, computerNameBufPtr, computerNameBufLength, smartCardDeviceId); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + } + } + } + + /// + public bool ShouldPerformSecurityUpgrade() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ClientConnector"); + } + Raw.ConnectorFfiResultBoolBoxIronRdpError result = Raw.ClientConnector.ShouldPerformSecurityUpgrade(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + bool retVal = result.Ok; + return retVal; + } + } + + /// + public void MarkSecurityUpgradeAsDone() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ClientConnector"); + } + Raw.ConnectorFfiResultVoidBoxIronRdpError result = Raw.ClientConnector.MarkSecurityUpgradeAsDone(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + } + } + + /// + public bool ShouldPerformCredssp() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ClientConnector"); + } + Raw.ConnectorFfiResultBoolBoxIronRdpError result = Raw.ClientConnector.ShouldPerformCredssp(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + bool retVal = result.Ok; + return retVal; + } + } + + /// + public void MarkCredsspAsDone() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ClientConnector"); + } + Raw.ConnectorFfiResultVoidBoxIronRdpError result = Raw.ClientConnector.MarkCredsspAsDone(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + } + } + + /// + /// + /// A Written allocated on Rust side. + /// + public Written Step(byte[] input, WriteBuf writeBuf) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ClientConnector"); + } + nuint inputLength = (nuint)input.Length; + Raw.WriteBuf* writeBufRaw; + writeBufRaw = writeBuf.AsFFI(); + if (writeBufRaw == null) + { + throw new ObjectDisposedException("WriteBuf"); + } + fixed (byte* inputPtr = input) + { + Raw.ConnectorFfiResultBoxWrittenBoxIronRdpError result = Raw.ClientConnector.Step(_inner, inputPtr, inputLength, writeBufRaw); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.Written* retVal = result.Ok; + return new Written(retVal); + } + } + } + + /// + /// + /// A Written allocated on Rust side. + /// + public Written StepNoInput(WriteBuf writeBuf) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ClientConnector"); + } + Raw.WriteBuf* writeBufRaw; + writeBufRaw = writeBuf.AsFFI(); + if (writeBufRaw == null) + { + throw new ObjectDisposedException("WriteBuf"); + } + Raw.ConnectorFfiResultBoxWrittenBoxIronRdpError result = Raw.ClientConnector.StepNoInput(_inner, writeBufRaw); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.Written* retVal = result.Ok; + return new Written(retVal); + } + } + + /// + /// + /// A PduHint allocated on Rust side. + /// + public PduHint NextPduHint() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ClientConnector"); + } + Raw.ConnectorFfiResultOptBoxPduHintBoxIronRdpError result = Raw.ClientConnector.NextPduHint(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.PduHint* retVal = result.Ok; + if (retVal == null) + { + return null; + } + return new PduHint(retVal); + } + } + + /// + /// + /// A State allocated on Rust side. + /// + public State State() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ClientConnector"); + } + Raw.ConnectorFfiResultBoxStateBoxIronRdpError result = Raw.ClientConnector.State(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.State* retVal = result.Ok; + return new State(retVal); + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.ClientConnector* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.ClientConnector.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~ClientConnector() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/ClientConnectorState.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/ClientConnectorState.cs new file mode 100644 index 000000000..127bc83cb --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/ClientConnectorState.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 ClientConnectorState: IDisposable +{ + private unsafe Raw.ClientConnectorState* _inner; + + /// + /// Creates a managed ClientConnectorState 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 ClientConnectorState(Raw.ClientConnectorState* handle) + { + _inner = handle; + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.ClientConnectorState* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.ClientConnectorState.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~ClientConnectorState() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/ClientState.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/ClientState.cs new file mode 100644 index 000000000..7b52b51e5 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/ClientState.cs @@ -0,0 +1,119 @@ +// 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 ClientState: IDisposable +{ + private unsafe Raw.ClientState* _inner; + + public TsRequest TsRequest + { + get + { + return GetTsRequest(); + } + } + + /// + /// Creates a managed ClientState 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 ClientState(Raw.ClientState* handle) + { + _inner = handle; + } + + public bool IsReplyNeeded() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ClientState"); + } + bool retVal = Raw.ClientState.IsReplyNeeded(_inner); + return retVal; + } + } + + public bool IsFinalMessage() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ClientState"); + } + bool retVal = Raw.ClientState.IsFinalMessage(_inner); + return retVal; + } + } + + /// + /// + /// A TsRequest allocated on Rust side. + /// + public TsRequest GetTsRequest() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ClientState"); + } + Raw.CredsspNetworkFfiResultBoxTsRequestBoxIronRdpError result = Raw.ClientState.GetTsRequest(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.TsRequest* retVal = result.Ok; + return new TsRequest(retVal); + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.ClientState* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.ClientState.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~ClientState() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/Config.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/Config.cs new file mode 100644 index 000000000..e234f4823 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/Config.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 Config: IDisposable +{ + private unsafe Raw.Config* _inner; + + /// + /// Creates a managed Config 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 Config(Raw.Config* handle) + { + _inner = handle; + } + + /// + /// A ConfigBuilder allocated on Rust side. + /// + public static ConfigBuilder GetBuilder() + { + unsafe + { + Raw.ConfigBuilder* retVal = Raw.Config.GetBuilder(); + return new ConfigBuilder(retVal); + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.Config* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.Config.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~Config() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/ConfigBuilder.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/ConfigBuilder.cs new file mode 100644 index 000000000..b3f46e34f --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/ConfigBuilder.cs @@ -0,0 +1,464 @@ +// 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 ConfigBuilder: IDisposable +{ + private unsafe Raw.ConfigBuilder* _inner; + + public bool Autologon + { + set + { + SetAutologon(value); + } + } + + public uint ClientBuild + { + set + { + SetClientBuild(value); + } + } + + public string ClientDir + { + set + { + SetClientDir(value); + } + } + + public string ClientName + { + set + { + SetClientName(value); + } + } + + public string DigProductId + { + set + { + SetDigProductId(value); + } + } + + public string Domain + { + set + { + SetDomain(value); + } + } + + public bool EnableCredssp + { + set + { + SetEnableCredssp(value); + } + } + + public bool EnableTls + { + set + { + SetEnableTls(value); + } + } + + public string ImeFileName + { + set + { + SetImeFileName(value); + } + } + + public uint KeyboardFunctionalKeysCount + { + set + { + SetKeyboardFunctionalKeysCount(value); + } + } + + public uint KeyboardSubtype + { + set + { + SetKeyboardSubtype(value); + } + } + + public KeyboardType KeyboardType + { + set + { + SetKeyboardType(value); + } + } + + public bool NoServerPointer + { + set + { + SetNoServerPointer(value); + } + } + + public PerformanceFlags PerformanceFlags + { + set + { + SetPerformanceFlags(value); + } + } + + public bool PointerSoftwareRendering + { + set + { + SetPointerSoftwareRendering(value); + } + } + + /// + /// Creates a managed ConfigBuilder 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 ConfigBuilder(Raw.ConfigBuilder* handle) + { + _inner = handle; + } + + /// + /// A ConfigBuilder allocated on Rust side. + /// + public static ConfigBuilder New() + { + unsafe + { + Raw.ConfigBuilder* retVal = Raw.ConfigBuilder.New(); + return new ConfigBuilder(retVal); + } + } + + public void WithUsernameAndPasswrord(string username, string password) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ConfigBuilder"); + } + byte[] usernameBuf = DiplomatUtils.StringToUtf8(username); + byte[] passwordBuf = DiplomatUtils.StringToUtf8(password); + nuint usernameBufLength = (nuint)usernameBuf.Length; + nuint passwordBufLength = (nuint)passwordBuf.Length; + fixed (byte* usernameBufPtr = usernameBuf) + { + fixed (byte* passwordBufPtr = passwordBuf) + { + Raw.ConfigBuilder.WithUsernameAndPasswrord(_inner, usernameBufPtr, usernameBufLength, passwordBufPtr, passwordBufLength); + } + } + } + } + + public void SetDomain(string domain) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ConfigBuilder"); + } + byte[] domainBuf = DiplomatUtils.StringToUtf8(domain); + nuint domainBufLength = (nuint)domainBuf.Length; + fixed (byte* domainBufPtr = domainBuf) + { + Raw.ConfigBuilder.SetDomain(_inner, domainBufPtr, domainBufLength); + } + } + } + + public void SetEnableTls(bool enableTls) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ConfigBuilder"); + } + Raw.ConfigBuilder.SetEnableTls(_inner, enableTls); + } + } + + public void SetEnableCredssp(bool enableCredssp) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ConfigBuilder"); + } + Raw.ConfigBuilder.SetEnableCredssp(_inner, enableCredssp); + } + } + + public void SetKeyboardType(KeyboardType keyboardType) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ConfigBuilder"); + } + Raw.KeyboardType keyboardTypeRaw; + keyboardTypeRaw = (Raw.KeyboardType)keyboardType; + Raw.ConfigBuilder.SetKeyboardType(_inner, keyboardTypeRaw); + } + } + + public void SetKeyboardSubtype(uint keyboardSubtype) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ConfigBuilder"); + } + Raw.ConfigBuilder.SetKeyboardSubtype(_inner, keyboardSubtype); + } + } + + public void SetKeyboardFunctionalKeysCount(uint keyboardFunctionalKeysCount) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ConfigBuilder"); + } + Raw.ConfigBuilder.SetKeyboardFunctionalKeysCount(_inner, keyboardFunctionalKeysCount); + } + } + + public void SetImeFileName(string imeFileName) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ConfigBuilder"); + } + byte[] imeFileNameBuf = DiplomatUtils.StringToUtf8(imeFileName); + nuint imeFileNameBufLength = (nuint)imeFileNameBuf.Length; + fixed (byte* imeFileNameBufPtr = imeFileNameBuf) + { + Raw.ConfigBuilder.SetImeFileName(_inner, imeFileNameBufPtr, imeFileNameBufLength); + } + } + } + + public void SetDigProductId(string digProductId) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ConfigBuilder"); + } + byte[] digProductIdBuf = DiplomatUtils.StringToUtf8(digProductId); + nuint digProductIdBufLength = (nuint)digProductIdBuf.Length; + fixed (byte* digProductIdBufPtr = digProductIdBuf) + { + Raw.ConfigBuilder.SetDigProductId(_inner, digProductIdBufPtr, digProductIdBufLength); + } + } + } + + public void SetDesktopSize(ushort height, ushort width) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ConfigBuilder"); + } + Raw.ConfigBuilder.SetDesktopSize(_inner, height, width); + } + } + + public void SetPerformanceFlags(PerformanceFlags performanceFlags) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ConfigBuilder"); + } + Raw.PerformanceFlags* performanceFlagsRaw; + performanceFlagsRaw = performanceFlags.AsFFI(); + if (performanceFlagsRaw == null) + { + throw new ObjectDisposedException("PerformanceFlags"); + } + Raw.ConfigBuilder.SetPerformanceFlags(_inner, performanceFlagsRaw); + } + } + + public void SetClientBuild(uint clientBuild) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ConfigBuilder"); + } + Raw.ConfigBuilder.SetClientBuild(_inner, clientBuild); + } + } + + public void SetClientName(string clientName) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ConfigBuilder"); + } + byte[] clientNameBuf = DiplomatUtils.StringToUtf8(clientName); + nuint clientNameBufLength = (nuint)clientNameBuf.Length; + fixed (byte* clientNameBufPtr = clientNameBuf) + { + Raw.ConfigBuilder.SetClientName(_inner, clientNameBufPtr, clientNameBufLength); + } + } + } + + public void SetClientDir(string clientDir) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ConfigBuilder"); + } + byte[] clientDirBuf = DiplomatUtils.StringToUtf8(clientDir); + nuint clientDirBufLength = (nuint)clientDirBuf.Length; + fixed (byte* clientDirBufPtr = clientDirBuf) + { + Raw.ConfigBuilder.SetClientDir(_inner, clientDirBufPtr, clientDirBufLength); + } + } + } + + public void SetNoServerPointer(bool noServerPointer) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ConfigBuilder"); + } + Raw.ConfigBuilder.SetNoServerPointer(_inner, noServerPointer); + } + } + + public void SetAutologon(bool autologon) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ConfigBuilder"); + } + Raw.ConfigBuilder.SetAutologon(_inner, autologon); + } + } + + public void SetPointerSoftwareRendering(bool pointerSoftwareRendering) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ConfigBuilder"); + } + Raw.ConfigBuilder.SetPointerSoftwareRendering(_inner, pointerSoftwareRendering); + } + } + + /// + /// + /// A Config allocated on Rust side. + /// + public Config Build() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ConfigBuilder"); + } + Raw.ConnectorConfigFfiResultBoxConfigBoxIronRdpError result = Raw.ConfigBuilder.Build(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.Config* retVal = result.Ok; + return new Config(retVal); + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.ConfigBuilder* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.ConfigBuilder.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~ConfigBuilder() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/ConnectionResult.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/ConnectionResult.cs new file mode 100644 index 000000000..d1d84d4b8 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/ConnectionResult.cs @@ -0,0 +1,195 @@ +// 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 ConnectionResult: IDisposable +{ + private unsafe Raw.ConnectionResult* _inner; + + public DesktopSize DesktopSize + { + get + { + return GetDesktopSize(); + } + } + + public ushort IoChannelId + { + get + { + return GetIoChannelId(); + } + } + + public bool NoServerPointer + { + get + { + return GetNoServerPointer(); + } + } + + public bool PointerSoftwareRendering + { + get + { + return GetPointerSoftwareRendering(); + } + } + + public StaticChannelSet StaticChannels + { + get + { + return GetStaticChannels(); + } + } + + public ushort UserChannelId + { + get + { + return GetUserChannelId(); + } + } + + /// + /// Creates a managed ConnectionResult 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 ConnectionResult(Raw.ConnectionResult* handle) + { + _inner = handle; + } + + public ushort GetIoChannelId() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ConnectionResult"); + } + ushort retVal = Raw.ConnectionResult.GetIoChannelId(_inner); + return retVal; + } + } + + public ushort GetUserChannelId() + { + unsafe + { + if (_inner == null) + { + 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) + { + throw new ObjectDisposedException("ConnectionResult"); + } + Raw.StaticChannelSet* retVal = Raw.ConnectionResult.GetStaticChannels(_inner); + return new StaticChannelSet(retVal); + } + } + + /// + /// A DesktopSize allocated on Rust side. + /// + public DesktopSize GetDesktopSize() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ConnectionResult"); + } + Raw.DesktopSize* retVal = Raw.ConnectionResult.GetDesktopSize(_inner); + return new DesktopSize(retVal); + } + } + + public bool GetNoServerPointer() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ConnectionResult"); + } + bool retVal = Raw.ConnectionResult.GetNoServerPointer(_inner); + return retVal; + } + } + + public bool GetPointerSoftwareRendering() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("ConnectionResult"); + } + bool retVal = Raw.ConnectionResult.GetPointerSoftwareRendering(_inner); + return retVal; + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.ConnectionResult* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.ConnectionResult.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~ConnectionResult() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/CredsspProcessGenerator.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/CredsspProcessGenerator.cs new file mode 100644 index 000000000..a5d0f1024 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/CredsspProcessGenerator.cs @@ -0,0 +1,111 @@ +// 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 CredsspProcessGenerator: IDisposable +{ + private unsafe Raw.CredsspProcessGenerator* _inner; + + /// + /// Creates a managed CredsspProcessGenerator 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 CredsspProcessGenerator(Raw.CredsspProcessGenerator* handle) + { + _inner = handle; + } + + /// + /// + /// A GeneratorState allocated on Rust side. + /// + public GeneratorState Start() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("CredsspProcessGenerator"); + } + Raw.CredsspNetworkFfiResultBoxGeneratorStateBoxIronRdpError result = Raw.CredsspProcessGenerator.Start(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.GeneratorState* retVal = result.Ok; + return new GeneratorState(retVal); + } + } + + /// + /// + /// A GeneratorState allocated on Rust side. + /// + public GeneratorState Resume(byte[] response) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("CredsspProcessGenerator"); + } + nuint responseLength = (nuint)response.Length; + fixed (byte* responsePtr = response) + { + Raw.CredsspNetworkFfiResultBoxGeneratorStateBoxIronRdpError result = Raw.CredsspProcessGenerator.Resume(_inner, responsePtr, responseLength); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.GeneratorState* retVal = result.Ok; + return new GeneratorState(retVal); + } + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.CredsspProcessGenerator* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.CredsspProcessGenerator.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~CredsspProcessGenerator() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/CredsspSequence.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/CredsspSequence.cs new file mode 100644 index 000000000..e750795ca --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/CredsspSequence.cs @@ -0,0 +1,221 @@ +// 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 CredsspSequence: IDisposable +{ + private unsafe Raw.CredsspSequence* _inner; + + /// + /// Creates a managed CredsspSequence 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 CredsspSequence(Raw.CredsspSequence* handle) + { + _inner = handle; + } + + /// + /// A PduHint allocated on Rust side. + /// + public PduHint? NextPduHint() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("CredsspSequence"); + } + Raw.PduHint* retVal = Raw.CredsspSequence.NextPduHint(_inner); + if (retVal == null) + { + return null; + } + return new PduHint(retVal); + } + } + + /// + /// + /// A CredsspSequenceInitResult allocated on Rust side. + /// + public static CredsspSequenceInitResult Init(ClientConnector connector, string serverName, byte[] serverPublicKey, KerberosConfig? kerberoConfigs) + { + unsafe + { + byte[] serverNameBuf = DiplomatUtils.StringToUtf8(serverName); + nuint serverPublicKeyLength = (nuint)serverPublicKey.Length; + nuint serverNameBufLength = (nuint)serverNameBuf.Length; + Raw.ClientConnector* connectorRaw; + connectorRaw = connector.AsFFI(); + if (connectorRaw == null) + { + throw new ObjectDisposedException("ClientConnector"); + } + Raw.KerberosConfig* kerberoConfigsRaw; + if (kerberoConfigs == null) + { + kerberoConfigsRaw = null; + } + else + { + kerberoConfigsRaw = kerberoConfigs.AsFFI(); + if (kerberoConfigsRaw == null) + { + throw new ObjectDisposedException("KerberosConfig"); + } + } + fixed (byte* serverPublicKeyPtr = serverPublicKey) + { + fixed (byte* serverNameBufPtr = serverNameBuf) + { + Raw.CredsspFfiResultBoxCredsspSequenceInitResultBoxIronRdpError result = Raw.CredsspSequence.Init(connectorRaw, serverNameBufPtr, serverNameBufLength, serverPublicKeyPtr, serverPublicKeyLength, kerberoConfigsRaw); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.CredsspSequenceInitResult* retVal = result.Ok; + return new CredsspSequenceInitResult(retVal); + } + } + } + } + + /// + /// + /// A TsRequest allocated on Rust side. + /// + public TsRequest DecodeServerMessage(byte[] pdu) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("CredsspSequence"); + } + nuint pduLength = (nuint)pdu.Length; + fixed (byte* pduPtr = pdu) + { + Raw.CredsspFfiResultOptBoxTsRequestBoxIronRdpError result = Raw.CredsspSequence.DecodeServerMessage(_inner, pduPtr, pduLength); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.TsRequest* retVal = result.Ok; + if (retVal == null) + { + return null; + } + return new TsRequest(retVal); + } + } + } + + /// + /// + /// A CredsspProcessGenerator allocated on Rust side. + /// + public CredsspProcessGenerator ProcessTsRequest(TsRequest tsRequest) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("CredsspSequence"); + } + Raw.TsRequest* tsRequestRaw; + tsRequestRaw = tsRequest.AsFFI(); + if (tsRequestRaw == null) + { + throw new ObjectDisposedException("TsRequest"); + } + Raw.CredsspFfiResultBoxCredsspProcessGeneratorBoxIronRdpError result = Raw.CredsspSequence.ProcessTsRequest(_inner, tsRequestRaw); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.CredsspProcessGenerator* retVal = result.Ok; + return new CredsspProcessGenerator(retVal); + } + } + + /// + /// + /// A Written allocated on Rust side. + /// + public Written HandleProcessResult(ClientState clientState, WriteBuf buf) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("CredsspSequence"); + } + Raw.ClientState* clientStateRaw; + clientStateRaw = clientState.AsFFI(); + if (clientStateRaw == null) + { + throw new ObjectDisposedException("ClientState"); + } + Raw.WriteBuf* bufRaw; + bufRaw = buf.AsFFI(); + if (bufRaw == null) + { + throw new ObjectDisposedException("WriteBuf"); + } + Raw.CredsspFfiResultBoxWrittenBoxIronRdpError result = Raw.CredsspSequence.HandleProcessResult(_inner, clientStateRaw, bufRaw); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.Written* retVal = result.Ok; + return new Written(retVal); + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.CredsspSequence* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.CredsspSequence.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~CredsspSequence() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/CredsspSequenceInitResult.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/CredsspSequenceInitResult.cs new file mode 100644 index 000000000..658a8c620 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/CredsspSequenceInitResult.cs @@ -0,0 +1,123 @@ +// 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 CredsspSequenceInitResult: IDisposable +{ + private unsafe Raw.CredsspSequenceInitResult* _inner; + + public CredsspSequence CredsspSequence + { + get + { + return GetCredsspSequence(); + } + } + + public TsRequest TsRequest + { + get + { + return GetTsRequest(); + } + } + + /// + /// Creates a managed CredsspSequenceInitResult 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 CredsspSequenceInitResult(Raw.CredsspSequenceInitResult* handle) + { + _inner = handle; + } + + /// + /// + /// A CredsspSequence allocated on Rust side. + /// + public CredsspSequence GetCredsspSequence() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("CredsspSequenceInitResult"); + } + Raw.CredsspFfiResultBoxCredsspSequenceBoxIronRdpError result = Raw.CredsspSequenceInitResult.GetCredsspSequence(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.CredsspSequence* retVal = result.Ok; + return new CredsspSequence(retVal); + } + } + + /// + /// + /// A TsRequest allocated on Rust side. + /// + public TsRequest GetTsRequest() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("CredsspSequenceInitResult"); + } + Raw.CredsspFfiResultBoxTsRequestBoxIronRdpError result = Raw.CredsspSequenceInitResult.GetTsRequest(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.TsRequest* retVal = result.Ok; + return new TsRequest(retVal); + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.CredsspSequenceInitResult* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.CredsspSequenceInitResult.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~CredsspSequenceInitResult() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/DesktopSize.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/DesktopSize.cs new file mode 100644 index 000000000..ecdb02070 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/DesktopSize.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 DesktopSize: IDisposable +{ + private unsafe Raw.DesktopSize* _inner; + + public ushort Height + { + get + { + return GetHeight(); + } + } + + public ushort Width + { + get + { + return GetWidth(); + } + } + + /// + /// Creates a managed DesktopSize 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 DesktopSize(Raw.DesktopSize* handle) + { + _inner = handle; + } + + public ushort GetWidth() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("DesktopSize"); + } + ushort retVal = Raw.DesktopSize.GetWidth(_inner); + return retVal; + } + } + + public ushort GetHeight() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("DesktopSize"); + } + ushort retVal = Raw.DesktopSize.GetHeight(_inner); + return retVal; + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.DesktopSize* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.DesktopSize.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~DesktopSize() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/DiplomatRuntime.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/DiplomatRuntime.cs new file mode 100644 index 000000000..18223e37b --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/DiplomatRuntime.cs @@ -0,0 +1,172 @@ +// Automatically generated by Diplomat + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; + +namespace Devolutions.IronRdp.Diplomat; + +#nullable enable + +[UnmanagedFunctionPointer(CallingConvention.Cdecl)] +delegate void WriteableFlush(IntPtr self); + +[UnmanagedFunctionPointer(CallingConvention.Cdecl)] +[return: MarshalAs(UnmanagedType.U1)] +delegate bool WriteableGrow(IntPtr self, nuint capacity); + +[Serializable] +[StructLayout(LayoutKind.Sequential)] +public struct DiplomatWriteable : IDisposable +{ + // About the current approach: + // Ideally DiplomatWriteable should wrap the native string type and grows/writes directly into the internal buffer. + // However, there is no native string type backed by UTF-8 in dotnet frameworks. + // Alternative could be to provide Diplomat's own `Utf8String` type, but this is not trivial and mostly useless + // on its own because all other dotnet/C# APIs are expecting the standard UTF-16 encoded string/String type. + // API is expected to become overall less ergonomic by forcing users to explicitly convert between UTF-16 and UTF-8 anyway in such case. + // It could be useful for copy-free interactions between Diplomat-generated API though. + // Also, there is no way to re-use the unmanaged buffer as-is to get a managed byte[] + // (hence `ToUtf8Bytes` is copying the internal buffer from unmanaged to managed memory). + // It's encouraged to enable memoization when applicable (#129). + + IntPtr context; + IntPtr buf; + nuint len; + nuint cap; + readonly IntPtr flush; + readonly IntPtr grow; + + public DiplomatWriteable() + { + WriteableFlush flushFunc = Flush; + WriteableGrow growFunc = Grow; + + IntPtr flushFuncPtr = Marshal.GetFunctionPointerForDelegate(flushFunc); + IntPtr growFuncPtr = Marshal.GetFunctionPointerForDelegate(growFunc); + + // flushFunc and growFunc are managed objects and might be disposed of by the garbage collector. + // To prevent this, we make the context hold the references and protect the context itself + // for automatic disposal by moving it behind a GCHandle. + DiplomatWriteableContext ctx = new DiplomatWriteableContext(); + ctx.flushFunc = flushFunc; + ctx.growFunc = growFunc; + GCHandle ctxHandle = GCHandle.Alloc(ctx); + + context = GCHandle.ToIntPtr(ctxHandle); + buf = Marshal.AllocHGlobal(64); + len = 0; + cap = 64; + flush = flushFuncPtr; + grow = growFuncPtr; + } + + public byte[] ToUtf8Bytes() + { + if (len > int.MaxValue) + { + throw new IndexOutOfRangeException("DiplomatWriteable buffer is too big"); + } + byte[] managedArray = new byte[(int)len]; + Marshal.Copy(buf, managedArray, 0, (int)len); + return managedArray; + } + + public string ToUnicode() + { +#if NET6_0_OR_GREATER + if (len > int.MaxValue) + { + throw new IndexOutOfRangeException("DiplomatWriteable buffer is too big"); + } + return Marshal.PtrToStringUTF8(buf, (int) len); +#else + byte[] utf8 = ToUtf8Bytes(); + return DiplomatUtils.Utf8ToString(utf8); +#endif + } + + public void Dispose() + { + if (buf != IntPtr.Zero) + { + Marshal.FreeHGlobal(buf); + buf = IntPtr.Zero; + } + + if (context != IntPtr.Zero) + { + GCHandle.FromIntPtr(context).Free(); + context = IntPtr.Zero; + } + } + + private static void Flush(IntPtr self) + { + // Nothing to do + } + + [return: MarshalAs(UnmanagedType.U1)] + private unsafe static bool Grow(IntPtr writeable, nuint capacity) + { + if (writeable == IntPtr.Zero) + { + return false; + } + DiplomatWriteable* self = (DiplomatWriteable*)writeable; + + nuint newCap = capacity; + if (newCap > int.MaxValue) + { + return false; + } + + IntPtr newBuf; + try + { + newBuf = Marshal.AllocHGlobal((int)newCap); + } + catch (OutOfMemoryException) + { + return false; + } + + Buffer.MemoryCopy((void*)self->buf, (void*)newBuf, newCap, self->cap); + Marshal.FreeHGlobal(self->buf); + self->buf = newBuf; + self->cap = newCap; + + return true; + } +} + +internal struct DiplomatWriteableContext +{ + internal WriteableFlush flushFunc; + internal WriteableGrow growFunc; +} + +internal static class DiplomatUtils +{ + internal static byte[] StringToUtf8(string s) + { + int size = Encoding.UTF8.GetByteCount(s); + byte[] buf = new byte[size]; + Encoding.UTF8.GetBytes(s, 0, s.Length, buf, 0); + return buf; + } + + internal static string Utf8ToString(byte[] utf8) + { + char[] chars = new char[utf8.Length]; + Encoding.UTF8.GetChars(utf8, 0, utf8.Length, chars, 0); + return new string(chars); + } +} + +public class DiplomatOpaqueException : Exception +{ + public DiplomatOpaqueException() : base("The FFI function failed with an opaque error") { } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/DrdynvcChannel.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/DrdynvcChannel.cs new file mode 100644 index 000000000..d42952916 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/DrdynvcChannel.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 DrdynvcChannel: IDisposable +{ + private unsafe Raw.DrdynvcChannel* _inner; + + /// + /// Creates a managed DrdynvcChannel 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 DrdynvcChannel(Raw.DrdynvcChannel* handle) + { + _inner = handle; + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.DrdynvcChannel* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.DrdynvcChannel.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~DrdynvcChannel() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/GeneratorState.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/GeneratorState.cs new file mode 100644 index 000000000..50a5c7d75 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/GeneratorState.cs @@ -0,0 +1,147 @@ +// 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 GeneratorState: IDisposable +{ + private unsafe Raw.GeneratorState* _inner; + + public ClientState ClientStateIfCompleted + { + get + { + return GetClientStateIfCompleted(); + } + } + + public NetworkRequest? NetworkRequestIfSuspended + { + get + { + return GetNetworkRequestIfSuspended(); + } + } + + /// + /// Creates a managed GeneratorState 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 GeneratorState(Raw.GeneratorState* handle) + { + _inner = handle; + } + + public bool IsSuspended() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("GeneratorState"); + } + bool retVal = Raw.GeneratorState.IsSuspended(_inner); + return retVal; + } + } + + public bool IsCompleted() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("GeneratorState"); + } + bool retVal = Raw.GeneratorState.IsCompleted(_inner); + return retVal; + } + } + + /// + /// A NetworkRequest allocated on Rust side. + /// + public NetworkRequest? GetNetworkRequestIfSuspended() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("GeneratorState"); + } + Raw.NetworkRequest* retVal = Raw.GeneratorState.GetNetworkRequestIfSuspended(_inner); + if (retVal == null) + { + return null; + } + return new NetworkRequest(retVal); + } + } + + /// + /// + /// A ClientState allocated on Rust side. + /// + public ClientState GetClientStateIfCompleted() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("GeneratorState"); + } + Raw.CredsspNetworkFfiResultBoxClientStateBoxIronRdpError result = Raw.GeneratorState.GetClientStateIfCompleted(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.ClientState* retVal = result.Ok; + return new ClientState(retVal); + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.GeneratorState* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.GeneratorState.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~GeneratorState() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/IronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/IronRdpError.cs new file mode 100644 index 000000000..d2c25abf9 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/IronRdpError.cs @@ -0,0 +1,127 @@ +// 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 + +/// +/// Stringified Picky error along with an error kind. +/// +public partial class IronRdpError: IDisposable +{ + private unsafe Raw.IronRdpError* _inner; + + public IronRdpErrorKind Kind + { + get + { + return GetKind(); + } + } + + /// + /// Creates a managed IronRdpError 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 IronRdpError(Raw.IronRdpError* handle) + { + _inner = handle; + } + + /// + /// Returns the error as a string. + /// + public void ToDisplay(DiplomatWriteable writeable) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("IronRdpError"); + } + Raw.IronRdpError.ToDisplay(_inner, &writeable); + } + } + + /// + /// Returns the error as a string. + /// + public string ToDisplay() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("IronRdpError"); + } + DiplomatWriteable writeable = new DiplomatWriteable(); + Raw.IronRdpError.ToDisplay(_inner, &writeable); + string retVal = writeable.ToUnicode(); + writeable.Dispose(); + return retVal; + } + } + + /// + /// Returns the error kind. + /// + /// + /// A IronRdpErrorKind allocated on C# side. + /// + public IronRdpErrorKind GetKind() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("IronRdpError"); + } + Raw.IronRdpErrorKind retVal = Raw.IronRdpError.GetKind(_inner); + return (IronRdpErrorKind)retVal; + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.IronRdpError* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.IronRdpError.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~IronRdpError() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/IronRdpErrorKind.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/IronRdpErrorKind.cs new file mode 100644 index 000000000..029758eac --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/IronRdpErrorKind.cs @@ -0,0 +1,22 @@ +// 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 IronRdpErrorKind +{ + Generic = 0, + PduError = 1, + CredsspError = 2, + Consumed = 3, + IO = 4, + AccessDenied = 5, +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/IronRdpException.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/IronRdpException.cs new file mode 100644 index 000000000..1dc629155 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/IronRdpException.cs @@ -0,0 +1,30 @@ +// 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 IronRdpException : Exception +{ + private IronRdpError _inner; + + public IronRdpException(IronRdpError inner) : base(inner.ToDisplay()) + { + _inner = inner; + } + + public IronRdpError Inner + { + get + { + return _inner; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/KerberosConfig.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/KerberosConfig.cs new file mode 100644 index 000000000..0cb7f570b --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/KerberosConfig.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 KerberosConfig: IDisposable +{ + private unsafe Raw.KerberosConfig* _inner; + + /// + /// Creates a managed KerberosConfig 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 KerberosConfig(Raw.KerberosConfig* handle) + { + _inner = handle; + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.KerberosConfig* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.KerberosConfig.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~KerberosConfig() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/KeyboardType.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/KeyboardType.cs new file mode 100644 index 000000000..fe13b4c60 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/KeyboardType.cs @@ -0,0 +1,23 @@ +// 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 KeyboardType +{ + IbmPcXt = 0, + OlivettiIco = 1, + IbmPcAt = 2, + IbmEnhanced = 3, + Nokia1050 = 4, + Nokia9140 = 5, + Japanese = 6, +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/NetworkRequest.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/NetworkRequest.cs new file mode 100644 index 000000000..88044c8a1 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/NetworkRequest.cs @@ -0,0 +1,157 @@ +// 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 NetworkRequest: IDisposable +{ + private unsafe Raw.NetworkRequest* _inner; + + public VecU8 Data + { + get + { + return GetData(); + } + } + + public NetworkRequestProtocol Protocol + { + get + { + return GetProtocol(); + } + } + + public string Url + { + get + { + return GetUrl(); + } + } + + /// + /// Creates a managed NetworkRequest 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 NetworkRequest(Raw.NetworkRequest* handle) + { + _inner = handle; + } + + /// + /// A VecU8 allocated on Rust side. + /// + public VecU8 GetData() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("NetworkRequest"); + } + Raw.VecU8* retVal = Raw.NetworkRequest.GetData(_inner); + return new VecU8(retVal); + } + } + + /// + /// A NetworkRequestProtocol allocated on C# side. + /// + public NetworkRequestProtocol GetProtocol() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("NetworkRequest"); + } + Raw.NetworkRequestProtocol retVal = Raw.NetworkRequest.GetProtocol(_inner); + return (NetworkRequestProtocol)retVal; + } + } + + /// + public void GetUrl(DiplomatWriteable writeable) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("NetworkRequest"); + } + Raw.CredsspNetworkFfiResultVoidBoxIronRdpError result = Raw.NetworkRequest.GetUrl(_inner, &writeable); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + } + } + + /// + public string GetUrl() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("NetworkRequest"); + } + DiplomatWriteable writeable = new DiplomatWriteable(); + Raw.CredsspNetworkFfiResultVoidBoxIronRdpError result = Raw.NetworkRequest.GetUrl(_inner, &writeable); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + string retVal = writeable.ToUnicode(); + writeable.Dispose(); + return retVal; + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.NetworkRequest* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.NetworkRequest.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~NetworkRequest() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/NetworkRequestProtocol.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/NetworkRequestProtocol.cs new file mode 100644 index 000000000..1dd231125 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/NetworkRequestProtocol.cs @@ -0,0 +1,20 @@ +// 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 NetworkRequestProtocol +{ + Tcp = 0, + Udp = 1, + Http = 2, + Https = 3, +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/OptionalUsize.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/OptionalUsize.cs new file mode 100644 index 000000000..1d8621a4c --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/OptionalUsize.cs @@ -0,0 +1,95 @@ +// 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 OptionalUsize: IDisposable +{ + private unsafe Raw.OptionalUsize* _inner; + + /// + /// Creates a managed OptionalUsize 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 OptionalUsize(Raw.OptionalUsize* handle) + { + _inner = handle; + } + + public bool IsSome() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("OptionalUsize"); + } + bool retVal = Raw.OptionalUsize.IsSome(_inner); + return retVal; + } + } + + /// + public nuint Get() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("OptionalUsize"); + } + Raw.UtilsFfiResultUsizeBoxIronRdpError result = Raw.OptionalUsize.Get(_inner); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + nuint retVal = result.Ok; + return retVal; + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.OptionalUsize* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.OptionalUsize.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~OptionalUsize() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/PduHint.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/PduHint.cs new file mode 100644 index 000000000..6969ca84c --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/PduHint.cs @@ -0,0 +1,89 @@ +// 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 PduHint: IDisposable +{ + private unsafe Raw.PduHint* _inner; + + /// + /// Creates a managed PduHint 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 PduHint(Raw.PduHint* handle) + { + _inner = handle; + } + + /// + /// + /// A OptionalUsize allocated on Rust side. + /// + public OptionalUsize FindSize(byte[] bytes) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("PduHint"); + } + nuint bytesLength = (nuint)bytes.Length; + fixed (byte* bytesPtr = bytes) + { + Raw.ConnectorFfiResultBoxOptionalUsizeBoxIronRdpError result = Raw.PduHint.FindSize(_inner, bytesPtr, bytesLength); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + Raw.OptionalUsize* retVal = result.Ok; + return new OptionalUsize(retVal); + } + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.PduHint* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.PduHint.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~PduHint() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/PerformanceFlags.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/PerformanceFlags.cs new file mode 100644 index 000000000..e49b7e57f --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/PerformanceFlags.cs @@ -0,0 +1,101 @@ +// 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 PerformanceFlags: IDisposable +{ + private unsafe Raw.PerformanceFlags* _inner; + + /// + /// Creates a managed PerformanceFlags 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 PerformanceFlags(Raw.PerformanceFlags* handle) + { + _inner = handle; + } + + /// + /// A PerformanceFlags allocated on Rust side. + /// + public static PerformanceFlags NewDefault() + { + unsafe + { + Raw.PerformanceFlags* retVal = Raw.PerformanceFlags.NewDefault(); + return new PerformanceFlags(retVal); + } + } + + /// + /// A PerformanceFlags allocated on Rust side. + /// + public static PerformanceFlags NewEmpty() + { + unsafe + { + Raw.PerformanceFlags* retVal = Raw.PerformanceFlags.NewEmpty(); + return new PerformanceFlags(retVal); + } + } + + public void AddFlag(PerformanceFlagsType flag) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("PerformanceFlags"); + } + Raw.PerformanceFlagsType flagRaw; + flagRaw = (Raw.PerformanceFlagsType)flag; + Raw.PerformanceFlags.AddFlag(_inner, flagRaw); + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.PerformanceFlags* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.PerformanceFlags.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~PerformanceFlags() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/PerformanceFlagsType.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/PerformanceFlagsType.cs new file mode 100644 index 000000000..cab76e289 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/PerformanceFlagsType.cs @@ -0,0 +1,26 @@ +// 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 PerformanceFlagsType +{ + DisableWallpaper = 0, + DisableFullWindowDrag = 1, + DisableMenuAnimations = 2, + DisableTheming = 3, + Reserved1 = 4, + DisableCursorShadow = 5, + DisableCursorSettings = 6, + EnableFontSmoothing = 7, + EnableDesktopComposition = 8, + Reserved2 = 9, +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawClientConnector.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawClientConnector.cs new file mode 100644 index 000000000..ce46a8ddc --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawClientConnector.cs @@ -0,0 +1,66 @@ +// 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 ClientConnector +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnector_new", ExactSpelling = true)] + public static unsafe extern ClientConnector* New(Config* config); + + /// + /// Must use + /// + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnector_with_server_addr", ExactSpelling = true)] + public static unsafe extern ConnectorFfiResultVoidBoxIronRdpError WithServerAddr(ClientConnector* self, byte* serverAddr, nuint serverAddrSz); + + /// + /// Must use + /// + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnector_with_static_channel_rdp_snd", ExactSpelling = true)] + public static unsafe extern ConnectorFfiResultVoidBoxIronRdpError WithStaticChannelRdpSnd(ClientConnector* self); + + /// + /// Must use + /// + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnector_with_static_channel_rdpdr", ExactSpelling = true)] + public static unsafe extern ConnectorFfiResultVoidBoxIronRdpError WithStaticChannelRdpdr(ClientConnector* self, byte* computerName, nuint computerNameSz, uint smartCardDeviceId); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnector_should_perform_security_upgrade", ExactSpelling = true)] + public static unsafe extern ConnectorFfiResultBoolBoxIronRdpError ShouldPerformSecurityUpgrade(ClientConnector* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnector_mark_security_upgrade_as_done", ExactSpelling = true)] + public static unsafe extern ConnectorFfiResultVoidBoxIronRdpError MarkSecurityUpgradeAsDone(ClientConnector* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnector_should_perform_credssp", ExactSpelling = true)] + public static unsafe extern ConnectorFfiResultBoolBoxIronRdpError ShouldPerformCredssp(ClientConnector* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnector_mark_credssp_as_done", ExactSpelling = true)] + public static unsafe extern ConnectorFfiResultVoidBoxIronRdpError MarkCredsspAsDone(ClientConnector* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnector_step", ExactSpelling = true)] + public static unsafe extern ConnectorFfiResultBoxWrittenBoxIronRdpError Step(ClientConnector* self, byte* input, nuint inputSz, WriteBuf* writeBuf); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnector_step_no_input", ExactSpelling = true)] + public static unsafe extern ConnectorFfiResultBoxWrittenBoxIronRdpError StepNoInput(ClientConnector* self, WriteBuf* writeBuf); + + [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_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 new file mode 100644 index 000000000..669ae9c03 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawClientConnectorState.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 ClientConnectorState +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [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/RawClientState.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawClientState.cs new file mode 100644 index 000000000..5a694bc2a --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawClientState.cs @@ -0,0 +1,32 @@ +// 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 ClientState +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientState_is_reply_needed", ExactSpelling = true)] + [return: MarshalAs(UnmanagedType.U1)] + public static unsafe extern bool IsReplyNeeded(ClientState* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientState_is_final_message", ExactSpelling = true)] + [return: MarshalAs(UnmanagedType.U1)] + public static unsafe extern bool IsFinalMessage(ClientState* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientState_get_ts_request", ExactSpelling = true)] + public static unsafe extern CredsspNetworkFfiResultBoxTsRequestBoxIronRdpError GetTsRequest(ClientState* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientState_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(ClientState* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConfig.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConfig.cs new file mode 100644 index 000000000..1eb7592e2 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConfig.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 Config +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Config_get_builder", ExactSpelling = true)] + public static unsafe extern ConfigBuilder* GetBuilder(); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Config_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(Config* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConfigBuilder.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConfigBuilder.cs new file mode 100644 index 000000000..ac96aefb7 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConfigBuilder.cs @@ -0,0 +1,78 @@ +// 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 ConfigBuilder +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [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_set_domain", ExactSpelling = true)] + public static unsafe extern void SetDomain(ConfigBuilder* self, byte* domain, nuint domainSz); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConfigBuilder_set_enable_tls", ExactSpelling = true)] + public static unsafe extern void SetEnableTls(ConfigBuilder* self, [MarshalAs(UnmanagedType.U1)] bool enableTls); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConfigBuilder_set_enable_credssp", ExactSpelling = true)] + public static unsafe extern void SetEnableCredssp(ConfigBuilder* self, [MarshalAs(UnmanagedType.U1)] bool enableCredssp); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConfigBuilder_set_keyboard_type", ExactSpelling = true)] + public static unsafe extern void SetKeyboardType(ConfigBuilder* self, KeyboardType keyboardType); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConfigBuilder_set_keyboard_subtype", ExactSpelling = true)] + public static unsafe extern void SetKeyboardSubtype(ConfigBuilder* self, uint keyboardSubtype); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConfigBuilder_set_keyboard_functional_keys_count", ExactSpelling = true)] + public static unsafe extern void SetKeyboardFunctionalKeysCount(ConfigBuilder* self, uint keyboardFunctionalKeysCount); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConfigBuilder_set_ime_file_name", ExactSpelling = true)] + public static unsafe extern void SetImeFileName(ConfigBuilder* self, byte* imeFileName, nuint imeFileNameSz); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConfigBuilder_set_dig_product_id", ExactSpelling = true)] + public static unsafe extern void SetDigProductId(ConfigBuilder* self, byte* digProductId, nuint digProductIdSz); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConfigBuilder_set_desktop_size", ExactSpelling = true)] + public static unsafe extern void SetDesktopSize(ConfigBuilder* self, ushort height, ushort width); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConfigBuilder_set_performance_flags", ExactSpelling = true)] + public static unsafe extern void SetPerformanceFlags(ConfigBuilder* self, PerformanceFlags* performanceFlags); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConfigBuilder_set_client_build", ExactSpelling = true)] + public static unsafe extern void SetClientBuild(ConfigBuilder* self, uint clientBuild); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConfigBuilder_set_client_name", ExactSpelling = true)] + public static unsafe extern void SetClientName(ConfigBuilder* self, byte* clientName, nuint clientNameSz); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConfigBuilder_set_client_dir", ExactSpelling = true)] + public static unsafe extern void SetClientDir(ConfigBuilder* self, byte* clientDir, nuint clientDirSz); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConfigBuilder_set_no_server_pointer", ExactSpelling = true)] + public static unsafe extern void SetNoServerPointer(ConfigBuilder* self, [MarshalAs(UnmanagedType.U1)] bool noServerPointer); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConfigBuilder_set_autologon", ExactSpelling = true)] + public static unsafe extern void SetAutologon(ConfigBuilder* self, [MarshalAs(UnmanagedType.U1)] bool autologon); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConfigBuilder_set_pointer_software_rendering", ExactSpelling = true)] + public static unsafe extern void SetPointerSoftwareRendering(ConfigBuilder* self, [MarshalAs(UnmanagedType.U1)] bool pointerSoftwareRendering); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConfigBuilder_build", ExactSpelling = true)] + public static unsafe extern ConnectorConfigFfiResultBoxConfigBoxIronRdpError Build(ConfigBuilder* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConfigBuilder_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(ConfigBuilder* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectionResult.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectionResult.cs new file mode 100644 index 000000000..c8f51e3d1 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectionResult.cs @@ -0,0 +1,41 @@ +// 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 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); + + [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); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ConnectionResult_get_desktop_size", ExactSpelling = true)] + public static unsafe extern DesktopSize* 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); + + [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); + + [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/RawConnectorConfigFfiResultBoxConfigBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorConfigFfiResultBoxConfigBoxIronRdpError.cs new file mode 100644 index 000000000..e2e20bf79 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorConfigFfiResultBoxConfigBoxIronRdpError.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 ConnectorConfigFfiResultBoxConfigBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal Config* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe Config* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoolBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoolBoxIronRdpError.cs new file mode 100644 index 000000000..7fc158904 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoolBoxIronRdpError.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 ConnectorFfiResultBoolBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal bool ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe bool Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoxOptionalUsizeBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoxOptionalUsizeBoxIronRdpError.cs new file mode 100644 index 000000000..ab190029d --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoxOptionalUsizeBoxIronRdpError.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 ConnectorFfiResultBoxOptionalUsizeBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal OptionalUsize* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe OptionalUsize* 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/RawConnectorFfiResultBoxStateBoxIronRdpError.cs new file mode 100644 index 000000000..52c4cae5f --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoxStateBoxIronRdpError.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 ConnectorFfiResultBoxStateBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal State* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe State* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoxWrittenBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoxWrittenBoxIronRdpError.cs new file mode 100644 index 000000000..efb13c479 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultBoxWrittenBoxIronRdpError.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 ConnectorFfiResultBoxWrittenBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal Written* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe Written* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultOptBoxPduHintBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultOptBoxPduHintBoxIronRdpError.cs new file mode 100644 index 000000000..c5fdf932e --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultOptBoxPduHintBoxIronRdpError.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 ConnectorFfiResultOptBoxPduHintBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal PduHint* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe PduHint* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultVoidBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultVoidBoxIronRdpError.cs new file mode 100644 index 000000000..5c652dc22 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawConnectorFfiResultVoidBoxIronRdpError.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 ConnectorFfiResultVoidBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspFfiResultBoxCredsspProcessGeneratorBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspFfiResultBoxCredsspProcessGeneratorBoxIronRdpError.cs new file mode 100644 index 000000000..ce13d18a3 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspFfiResultBoxCredsspProcessGeneratorBoxIronRdpError.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 CredsspFfiResultBoxCredsspProcessGeneratorBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal CredsspProcessGenerator* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe CredsspProcessGenerator* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspFfiResultBoxCredsspSequenceBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspFfiResultBoxCredsspSequenceBoxIronRdpError.cs new file mode 100644 index 000000000..57da8cd7b --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspFfiResultBoxCredsspSequenceBoxIronRdpError.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 CredsspFfiResultBoxCredsspSequenceBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal CredsspSequence* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe CredsspSequence* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspFfiResultBoxCredsspSequenceInitResultBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspFfiResultBoxCredsspSequenceInitResultBoxIronRdpError.cs new file mode 100644 index 000000000..d8602e290 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspFfiResultBoxCredsspSequenceInitResultBoxIronRdpError.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 CredsspFfiResultBoxCredsspSequenceInitResultBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal CredsspSequenceInitResult* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe CredsspSequenceInitResult* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspFfiResultBoxTsRequestBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspFfiResultBoxTsRequestBoxIronRdpError.cs new file mode 100644 index 000000000..9da0daa76 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspFfiResultBoxTsRequestBoxIronRdpError.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 CredsspFfiResultBoxTsRequestBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal TsRequest* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe TsRequest* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspFfiResultBoxWrittenBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspFfiResultBoxWrittenBoxIronRdpError.cs new file mode 100644 index 000000000..b7e2a675d --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspFfiResultBoxWrittenBoxIronRdpError.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 CredsspFfiResultBoxWrittenBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal Written* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe Written* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspFfiResultOptBoxTsRequestBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspFfiResultOptBoxTsRequestBoxIronRdpError.cs new file mode 100644 index 000000000..6c104178f --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspFfiResultOptBoxTsRequestBoxIronRdpError.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 CredsspFfiResultOptBoxTsRequestBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal TsRequest* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe TsRequest* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspNetworkFfiResultBoxClientStateBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspNetworkFfiResultBoxClientStateBoxIronRdpError.cs new file mode 100644 index 000000000..ba55c276c --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspNetworkFfiResultBoxClientStateBoxIronRdpError.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 CredsspNetworkFfiResultBoxClientStateBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal ClientState* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe ClientState* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspNetworkFfiResultBoxGeneratorStateBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspNetworkFfiResultBoxGeneratorStateBoxIronRdpError.cs new file mode 100644 index 000000000..2b7fb20a7 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspNetworkFfiResultBoxGeneratorStateBoxIronRdpError.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 CredsspNetworkFfiResultBoxGeneratorStateBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal GeneratorState* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe GeneratorState* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspNetworkFfiResultBoxTsRequestBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspNetworkFfiResultBoxTsRequestBoxIronRdpError.cs new file mode 100644 index 000000000..e79b9b37f --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspNetworkFfiResultBoxTsRequestBoxIronRdpError.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 CredsspNetworkFfiResultBoxTsRequestBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal TsRequest* ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe TsRequest* Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspNetworkFfiResultVoidBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspNetworkFfiResultVoidBoxIronRdpError.cs new file mode 100644 index 000000000..61de7b3e6 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspNetworkFfiResultVoidBoxIronRdpError.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 CredsspNetworkFfiResultVoidBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspProcessGenerator.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspProcessGenerator.cs new file mode 100644 index 000000000..919fed6d2 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspProcessGenerator.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 CredsspProcessGenerator +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "CredsspProcessGenerator_start", ExactSpelling = true)] + public static unsafe extern CredsspNetworkFfiResultBoxGeneratorStateBoxIronRdpError Start(CredsspProcessGenerator* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "CredsspProcessGenerator_resume", ExactSpelling = true)] + public static unsafe extern CredsspNetworkFfiResultBoxGeneratorStateBoxIronRdpError Resume(CredsspProcessGenerator* self, byte* response, nuint responseSz); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "CredsspProcessGenerator_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(CredsspProcessGenerator* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspSequence.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspSequence.cs new file mode 100644 index 000000000..0029d7f23 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspSequence.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 CredsspSequence +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "CredsspSequence_next_pdu_hint", ExactSpelling = true)] + public static unsafe extern PduHint* NextPduHint(CredsspSequence* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "CredsspSequence_init", ExactSpelling = true)] + public static unsafe extern CredsspFfiResultBoxCredsspSequenceInitResultBoxIronRdpError Init(ClientConnector* connector, byte* serverName, nuint serverNameSz, byte* serverPublicKey, nuint serverPublicKeySz, KerberosConfig* kerberoConfigs); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "CredsspSequence_decode_server_message", ExactSpelling = true)] + public static unsafe extern CredsspFfiResultOptBoxTsRequestBoxIronRdpError DecodeServerMessage(CredsspSequence* self, byte* pdu, nuint pduSz); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "CredsspSequence_process_ts_request", ExactSpelling = true)] + public static unsafe extern CredsspFfiResultBoxCredsspProcessGeneratorBoxIronRdpError ProcessTsRequest(CredsspSequence* self, TsRequest* tsRequest); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "CredsspSequence_handle_process_result", ExactSpelling = true)] + public static unsafe extern CredsspFfiResultBoxWrittenBoxIronRdpError HandleProcessResult(CredsspSequence* self, ClientState* clientState, WriteBuf* buf); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "CredsspSequence_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(CredsspSequence* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspSequenceInitResult.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspSequenceInitResult.cs new file mode 100644 index 000000000..fa340166b --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawCredsspSequenceInitResult.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 CredsspSequenceInitResult +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "CredsspSequenceInitResult_get_credssp_sequence", ExactSpelling = true)] + public static unsafe extern CredsspFfiResultBoxCredsspSequenceBoxIronRdpError GetCredsspSequence(CredsspSequenceInitResult* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "CredsspSequenceInitResult_get_ts_request", ExactSpelling = true)] + public static unsafe extern CredsspFfiResultBoxTsRequestBoxIronRdpError GetTsRequest(CredsspSequenceInitResult* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "CredsspSequenceInitResult_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(CredsspSequenceInitResult* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawDesktopSize.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawDesktopSize.cs new file mode 100644 index 000000000..e902c7ff7 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawDesktopSize.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 DesktopSize +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DesktopSize_get_width", ExactSpelling = true)] + public static unsafe extern ushort GetWidth(DesktopSize* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DesktopSize_get_height", ExactSpelling = true)] + public static unsafe extern ushort GetHeight(DesktopSize* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DesktopSize_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(DesktopSize* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawDrdynvcChannel.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawDrdynvcChannel.cs new file mode 100644 index 000000000..124d54dda --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawDrdynvcChannel.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 DrdynvcChannel +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DrdynvcChannel_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(DrdynvcChannel* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawGeneratorState.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawGeneratorState.cs new file mode 100644 index 000000000..29bf6ba7c --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawGeneratorState.cs @@ -0,0 +1,35 @@ +// 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 GeneratorState +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "GeneratorState_is_suspended", ExactSpelling = true)] + [return: MarshalAs(UnmanagedType.U1)] + public static unsafe extern bool IsSuspended(GeneratorState* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "GeneratorState_is_completed", ExactSpelling = true)] + [return: MarshalAs(UnmanagedType.U1)] + public static unsafe extern bool IsCompleted(GeneratorState* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "GeneratorState_get_network_request_if_suspended", ExactSpelling = true)] + public static unsafe extern NetworkRequest* GetNetworkRequestIfSuspended(GeneratorState* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "GeneratorState_get_client_state_if_completed", ExactSpelling = true)] + public static unsafe extern CredsspNetworkFfiResultBoxClientStateBoxIronRdpError GetClientStateIfCompleted(GeneratorState* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "GeneratorState_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(GeneratorState* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawIronRdpError.cs new file mode 100644 index 000000000..680d5d9df --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawIronRdpError.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 + +/// +/// Stringified Picky error along with an error kind. +/// +[StructLayout(LayoutKind.Sequential)] +public partial struct IronRdpError +{ + private const string NativeLib = "DevolutionsIronRdp"; + + /// + /// Returns the error as a string. + /// + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "IronRdpError_to_display", ExactSpelling = true)] + public static unsafe extern void ToDisplay(IronRdpError* self, DiplomatWriteable* writeable); + + /// + /// Returns the error kind. + /// + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "IronRdpError_get_kind", ExactSpelling = true)] + public static unsafe extern IronRdpErrorKind GetKind(IronRdpError* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "IronRdpError_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(IronRdpError* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawIronRdpErrorKind.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawIronRdpErrorKind.cs new file mode 100644 index 000000000..83c1d0e1b --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawIronRdpErrorKind.cs @@ -0,0 +1,22 @@ +// 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 IronRdpErrorKind +{ + Generic = 0, + PduError = 1, + CredsspError = 2, + Consumed = 3, + IO = 4, + AccessDenied = 5, +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawKerberosConfig.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawKerberosConfig.cs new file mode 100644 index 000000000..410ff439b --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawKerberosConfig.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 KerberosConfig +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "KerberosConfig_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(KerberosConfig* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawKeyboardType.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawKeyboardType.cs new file mode 100644 index 000000000..baf5eda99 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawKeyboardType.cs @@ -0,0 +1,23 @@ +// 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 KeyboardType +{ + IbmPcXt = 0, + OlivettiIco = 1, + IbmPcAt = 2, + IbmEnhanced = 3, + Nokia1050 = 4, + Nokia9140 = 5, + Japanese = 6, +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawNetworkRequest.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawNetworkRequest.cs new file mode 100644 index 000000000..5fa5bc27a --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawNetworkRequest.cs @@ -0,0 +1,30 @@ +// 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 NetworkRequest +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "NetworkRequest_get_data", ExactSpelling = true)] + public static unsafe extern VecU8* GetData(NetworkRequest* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "NetworkRequest_get_protocol", ExactSpelling = true)] + public static unsafe extern NetworkRequestProtocol GetProtocol(NetworkRequest* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "NetworkRequest_get_url", ExactSpelling = true)] + public static unsafe extern CredsspNetworkFfiResultVoidBoxIronRdpError GetUrl(NetworkRequest* self, DiplomatWriteable* writeable); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "NetworkRequest_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(NetworkRequest* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawNetworkRequestProtocol.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawNetworkRequestProtocol.cs new file mode 100644 index 000000000..4c15f64e9 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawNetworkRequestProtocol.cs @@ -0,0 +1,20 @@ +// 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 NetworkRequestProtocol +{ + Tcp = 0, + Udp = 1, + Http = 2, + Https = 3, +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawOptionalUsize.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawOptionalUsize.cs new file mode 100644 index 000000000..42f3cbd9e --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawOptionalUsize.cs @@ -0,0 +1,28 @@ +// 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 OptionalUsize +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OptionalUsize_is_some", ExactSpelling = true)] + [return: MarshalAs(UnmanagedType.U1)] + public static unsafe extern bool IsSome(OptionalUsize* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OptionalUsize_get", ExactSpelling = true)] + public static unsafe extern UtilsFfiResultUsizeBoxIronRdpError Get(OptionalUsize* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "OptionalUsize_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(OptionalUsize* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawPduFfiResultVoidBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawPduFfiResultVoidBoxIronRdpError.cs new file mode 100644 index 000000000..90fcc2e61 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawPduFfiResultVoidBoxIronRdpError.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 PduFfiResultVoidBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawPduHint.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawPduHint.cs new file mode 100644 index 000000000..6252967e3 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawPduHint.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 PduHint +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PduHint_find_size", ExactSpelling = true)] + public static unsafe extern ConnectorFfiResultBoxOptionalUsizeBoxIronRdpError FindSize(PduHint* self, byte* bytes, nuint bytesSz); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PduHint_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(PduHint* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawPerformanceFlags.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawPerformanceFlags.cs new file mode 100644 index 000000000..fc5205801 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawPerformanceFlags.cs @@ -0,0 +1,30 @@ +// 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 PerformanceFlags +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PerformanceFlags_new_default", ExactSpelling = true)] + public static unsafe extern PerformanceFlags* NewDefault(); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PerformanceFlags_new_empty", ExactSpelling = true)] + public static unsafe extern PerformanceFlags* NewEmpty(); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PerformanceFlags_add_flag", ExactSpelling = true)] + public static unsafe extern void AddFlag(PerformanceFlags* self, PerformanceFlagsType flag); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PerformanceFlags_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(PerformanceFlags* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawPerformanceFlagsType.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawPerformanceFlagsType.cs new file mode 100644 index 000000000..05f5cd574 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawPerformanceFlagsType.cs @@ -0,0 +1,26 @@ +// 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 PerformanceFlagsType +{ + DisableWallpaper = 0, + DisableFullWindowDrag = 1, + DisableMenuAnimations = 2, + DisableTheming = 3, + Reserved1 = 4, + DisableCursorShadow = 5, + DisableCursorSettings = 6, + EnableFontSmoothing = 7, + EnableDesktopComposition = 8, + Reserved2 = 9, +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawState.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawState.cs new file mode 100644 index 000000000..99ea3e78f --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawState.cs @@ -0,0 +1,28 @@ +// 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 State +{ + 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 = "State_is_terminal", ExactSpelling = true)] + [return: MarshalAs(UnmanagedType.U1)] + public static unsafe extern bool IsTerminal(State* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "State_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(State* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawStaticChannelSet.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawStaticChannelSet.cs new file mode 100644 index 000000000..e7237ace8 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawStaticChannelSet.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 StaticChannelSet +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "StaticChannelSet_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(StaticChannelSet* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawTsRequest.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawTsRequest.cs new file mode 100644 index 000000000..e5b8f200a --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawTsRequest.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 TsRequest +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "TsRequest_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(TsRequest* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawUtilsFfiResultUsizeBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawUtilsFfiResultUsizeBoxIronRdpError.cs new file mode 100644 index 000000000..faaa2f53d --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawUtilsFfiResultUsizeBoxIronRdpError.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 UtilsFfiResultUsizeBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal nuint ok; + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe nuint Ok + { + get + { + return _inner.ok; + } + } + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawUtilsFfiResultVoidBoxIronRdpError.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawUtilsFfiResultVoidBoxIronRdpError.cs new file mode 100644 index 000000000..686bbfb02 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawUtilsFfiResultVoidBoxIronRdpError.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 UtilsFfiResultVoidBoxIronRdpError +{ + [StructLayout(LayoutKind.Explicit)] + private unsafe struct InnerUnion + { + [FieldOffset(0)] + internal IronRdpError* err; + } + + private InnerUnion _inner; + + [MarshalAs(UnmanagedType.U1)] + public bool isOk; + + public unsafe IronRdpError* Err + { + get + { + return _inner.err; + } + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawVecU8.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawVecU8.cs new file mode 100644 index 000000000..50b656777 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawVecU8.cs @@ -0,0 +1,33 @@ +// 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 VecU8 +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "VecU8_from_bytes", ExactSpelling = true)] + public static unsafe extern VecU8* FromBytes(byte* bytes, nuint bytesSz); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "VecU8_get_size", ExactSpelling = true)] + public static unsafe extern nuint GetSize(VecU8* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "VecU8_fill", ExactSpelling = true)] + public static unsafe extern UtilsFfiResultVoidBoxIronRdpError Fill(VecU8* self, byte* buffer, nuint bufferSz); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "VecU8_new_empty", ExactSpelling = true)] + public static unsafe extern VecU8* NewEmpty(); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "VecU8_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(VecU8* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawWriteBuf.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawWriteBuf.cs new file mode 100644 index 000000000..11af66f1b --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawWriteBuf.cs @@ -0,0 +1,30 @@ +// 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 WriteBuf +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "WriteBuf_new", ExactSpelling = true)] + public static unsafe extern WriteBuf* New(); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "WriteBuf_clear", ExactSpelling = true)] + public static unsafe extern void Clear(WriteBuf* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "WriteBuf_read_into_buf", ExactSpelling = true)] + public static unsafe extern PduFfiResultVoidBoxIronRdpError ReadIntoBuf(WriteBuf* self, byte* buf, nuint bufSz); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "WriteBuf_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(WriteBuf* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawWritten.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawWritten.cs new file mode 100644 index 000000000..6792ddb39 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawWritten.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 Written +{ + private const string NativeLib = "DevolutionsIronRdp"; + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Written_get_written_type", ExactSpelling = true)] + public static unsafe extern WrittenType GetWrittenType(Written* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Written_get_size", ExactSpelling = true)] + public static unsafe extern OptionalUsize* GetSize(Written* self); + + [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Written_destroy", ExactSpelling = true)] + public static unsafe extern void Destroy(Written* self); +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/RawWrittenType.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/RawWrittenType.cs new file mode 100644 index 000000000..5878798fc --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/RawWrittenType.cs @@ -0,0 +1,18 @@ +// 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 WrittenType +{ + Size = 0, + Nothing = 1, +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/State.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/State.cs new file mode 100644 index 000000000..7d9875390 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/State.cs @@ -0,0 +1,122 @@ +// 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 State: IDisposable +{ + private unsafe Raw.State* _inner; + + public string Name + { + get + { + return GetName(); + } + } + + /// + /// Creates a managed State 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 State(Raw.State* handle) + { + _inner = handle; + } + + /// + public void GetName(DiplomatWriteable writeable) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("State"); + } + Raw.ConnectorFfiResultVoidBoxIronRdpError result = Raw.State.GetName(_inner, &writeable); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + } + } + + /// + public string GetName() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("State"); + } + DiplomatWriteable writeable = new DiplomatWriteable(); + Raw.ConnectorFfiResultVoidBoxIronRdpError result = Raw.State.GetName(_inner, &writeable); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + string retVal = writeable.ToUnicode(); + writeable.Dispose(); + return retVal; + } + } + + public bool IsTerminal() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("State"); + } + bool retVal = Raw.State.IsTerminal(_inner); + return retVal; + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.State* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.State.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~State() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/StaticChannelSet.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/StaticChannelSet.cs new file mode 100644 index 000000000..3ee5e0f2a --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/StaticChannelSet.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 StaticChannelSet: IDisposable +{ + private unsafe Raw.StaticChannelSet* _inner; + + /// + /// Creates a managed StaticChannelSet 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 StaticChannelSet(Raw.StaticChannelSet* handle) + { + _inner = handle; + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.StaticChannelSet* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.StaticChannelSet.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~StaticChannelSet() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/TsRequest.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/TsRequest.cs new file mode 100644 index 000000000..6a3972a5d --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/TsRequest.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 TsRequest: IDisposable +{ + private unsafe Raw.TsRequest* _inner; + + /// + /// Creates a managed TsRequest 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 TsRequest(Raw.TsRequest* handle) + { + _inner = handle; + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.TsRequest* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.TsRequest.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~TsRequest() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/VecU8.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/VecU8.cs new file mode 100644 index 000000000..488d1e586 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/VecU8.cs @@ -0,0 +1,133 @@ +// 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 VecU8: IDisposable +{ + private unsafe Raw.VecU8* _inner; + + public nuint Size + { + get + { + return GetSize(); + } + } + + /// + /// Creates a managed VecU8 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 VecU8(Raw.VecU8* handle) + { + _inner = handle; + } + + /// + /// A VecU8 allocated on Rust side. + /// + public static VecU8 FromBytes(byte[] bytes) + { + unsafe + { + nuint bytesLength = (nuint)bytes.Length; + fixed (byte* bytesPtr = bytes) + { + Raw.VecU8* retVal = Raw.VecU8.FromBytes(bytesPtr, bytesLength); + return new VecU8(retVal); + } + } + } + + public nuint GetSize() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("VecU8"); + } + nuint retVal = Raw.VecU8.GetSize(_inner); + return retVal; + } + } + + /// + public void Fill(byte[] buffer) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("VecU8"); + } + nuint bufferLength = (nuint)buffer.Length; + fixed (byte* bufferPtr = buffer) + { + Raw.UtilsFfiResultVoidBoxIronRdpError result = Raw.VecU8.Fill(_inner, bufferPtr, bufferLength); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + } + } + } + + /// + /// A VecU8 allocated on Rust side. + /// + public static VecU8 NewEmpty() + { + unsafe + { + Raw.VecU8* retVal = Raw.VecU8.NewEmpty(); + return new VecU8(retVal); + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.VecU8* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.VecU8.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~VecU8() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/WriteBuf.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/WriteBuf.cs new file mode 100644 index 000000000..2d3244053 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/WriteBuf.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 WriteBuf: IDisposable +{ + private unsafe Raw.WriteBuf* _inner; + + /// + /// Creates a managed WriteBuf 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 WriteBuf(Raw.WriteBuf* handle) + { + _inner = handle; + } + + /// + /// A WriteBuf allocated on Rust side. + /// + public static WriteBuf New() + { + unsafe + { + Raw.WriteBuf* retVal = Raw.WriteBuf.New(); + return new WriteBuf(retVal); + } + } + + public void Clear() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("WriteBuf"); + } + Raw.WriteBuf.Clear(_inner); + } + } + + /// + public void ReadIntoBuf(byte[] buf) + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("WriteBuf"); + } + nuint bufLength = (nuint)buf.Length; + fixed (byte* bufPtr = buf) + { + Raw.PduFfiResultVoidBoxIronRdpError result = Raw.WriteBuf.ReadIntoBuf(_inner, bufPtr, bufLength); + if (!result.isOk) + { + throw new IronRdpException(new IronRdpError(result.Err)); + } + } + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.WriteBuf* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.WriteBuf.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~WriteBuf() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/Written.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/Written.cs new file mode 100644 index 000000000..c02d6cde3 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/Written.cs @@ -0,0 +1,111 @@ +// 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 Written: IDisposable +{ + private unsafe Raw.Written* _inner; + + public OptionalUsize Size + { + get + { + return GetSize(); + } + } + + public WrittenType WrittenType + { + get + { + return GetWrittenType(); + } + } + + /// + /// Creates a managed Written 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 Written(Raw.Written* handle) + { + _inner = handle; + } + + /// + /// A WrittenType allocated on C# side. + /// + public WrittenType GetWrittenType() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("Written"); + } + Raw.WrittenType retVal = Raw.Written.GetWrittenType(_inner); + return (WrittenType)retVal; + } + } + + /// + /// A OptionalUsize allocated on Rust side. + /// + public OptionalUsize GetSize() + { + unsafe + { + if (_inner == null) + { + throw new ObjectDisposedException("Written"); + } + Raw.OptionalUsize* retVal = Raw.Written.GetSize(_inner); + return new OptionalUsize(retVal); + } + } + + /// + /// Returns the underlying raw handle. + /// + public unsafe Raw.Written* AsFFI() + { + return _inner; + } + + /// + /// Destroys the underlying object immediately. + /// + public void Dispose() + { + unsafe + { + if (_inner == null) + { + return; + } + + Raw.Written.Destroy(_inner); + _inner = null; + + GC.SuppressFinalize(this); + } + } + + ~Written() + { + Dispose(); + } +} diff --git a/ffi/dotnet/Devolutions.IronRdp/Generated/WrittenType.cs b/ffi/dotnet/Devolutions.IronRdp/Generated/WrittenType.cs new file mode 100644 index 000000000..72c949257 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/Generated/WrittenType.cs @@ -0,0 +1,18 @@ +// 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 WrittenType +{ + Size = 0, + Nothing = 1, +} diff --git a/ffi/dotnet/Devolutions.IronRdp/src/Framed.cs b/ffi/dotnet/Devolutions.IronRdp/src/Framed.cs new file mode 100644 index 000000000..715b05407 --- /dev/null +++ b/ffi/dotnet/Devolutions.IronRdp/src/Framed.cs @@ -0,0 +1,95 @@ +using System.Runtime.InteropServices; +using Devolutions.IronRdp; + +public class Framed where S : Stream +{ + private S stream; + private List buffer; + + public Framed(S stream) + { + this.stream = stream; + this.buffer = new List(); + } + + public (S, List) GetInner() + { + return (this.stream, this.buffer); + } + + /// + /// Returns a span that represents a portion of the underlying buffer without modifying it. + /// + /// Memory safety: the Framed instance should not be modified (any read operations) while span is in use. + /// A span that represents a portion of the underlying buffer. + public Span Peek() + { + return CollectionsMarshal.AsSpan(this.buffer); + } + + /// + /// Reads from 0 to size bytes from the front of the buffer, and remove them from the buffer keeping the rest. + /// + /// The number of bytes to read. + /// An array of bytes containing the read data. + public async Task ReadExact(nuint size) + { + while (true) + { + if (buffer.Count >= (int)size) + { + var res = this.buffer.Take((int)size).ToArray(); + this.buffer = this.buffer.Skip((int)size).ToList(); + return res; + } + + var len = await this.Read(); + if (len == 0) + { + throw new Exception("EOF"); + } + } + } + + async Task Read() + { + var buffer = new byte[1024]; + Memory memory = buffer; + var size = await this.stream.ReadAsync(memory); + this.buffer.AddRange(buffer.Take(size)); + return size; + } + + public async Task Write(byte[] data) + { + ReadOnlyMemory memory = data; + await this.stream.WriteAsync(memory); + } + + + /// + /// Reads data from the buffer based on the provided PduHint. + /// + /// The PduHint object used to determine the size of the data to read. + /// An asynchronous task that represents the operation. The task result contains the read data as a byte array. + public async Task ReadByHint(PduHint pduHint) + { + while (true) + { + var size = pduHint.FindSize(this.buffer.ToArray()); + if (size.IsSome()) + { + return await this.ReadExact(size.Get()); + } + else + { + var len = await this.Read(); + if (len == 0) + { + throw new Exception("EOF"); + } + } + + } + } +} diff --git a/ffi/src/connector/config.rs b/ffi/src/connector/config.rs new file mode 100644 index 000000000..e70f30066 --- /dev/null +++ b/ffi/src/connector/config.rs @@ -0,0 +1,247 @@ +use ironrdp::pdu::rdp::client_info::PerformanceFlags; + +use self::ffi::PerformanceFlagsType; + +#[diplomat::bridge] +pub mod ffi { + use ironrdp::{ + connector::{BitmapConfig, Credentials}, + pdu::rdp::capability_sets::MajorPlatformType, + }; + + use crate::error::ffi::IronRdpError; + + #[diplomat::opaque] + pub struct Config(pub ironrdp::connector::Config); + + impl Config { + pub fn get_builder() -> Box { + Box::::default() + } + } + + #[derive(Default)] + #[diplomat::opaque] + pub struct ConfigBuilder { + pub credentials: Option, + pub domain: Option, + pub enable_tls: Option, + pub enable_credssp: Option, + pub keyboard_type: Option, + pub keyboard_subtype: Option, + pub keyboard_functional_keys_count: Option, + pub ime_file_name: Option, + pub dig_product_id: Option, + pub desktop_size: Option, + pub bitmap: Option, + pub client_build: Option, + pub client_name: Option, + pub client_dir: Option, + pub platform: Option, + pub no_server_pointer: Option, + pub autologon: Option, + pub pointer_software_rendering: Option, + pub performance_flags: Option, + } + + #[diplomat::enum_convert(ironrdp::pdu::gcc::KeyboardType)] + pub enum KeyboardType { + IbmPcXt, + OlivettiIco, + IbmPcAt, + IbmEnhanced, + Nokia1050, + Nokia9140, + Japanese, + } + + #[diplomat::opaque] + pub struct DesktopSize(pub ironrdp::connector::DesktopSize); + + impl DesktopSize { + pub fn get_width(&self) -> u16 { + self.0.width + } + + pub fn get_height(&self) -> u16 { + self.0.height + } + } + + impl ConfigBuilder { + pub fn new() -> Box { + Box::::default() + } + + pub fn with_username_and_password(&mut self, username: &str, password: &str) { + self.credentials = Some(Credentials::UsernamePassword { + username: username.to_owned(), + password: password.to_owned(), + }); + } + + pub fn set_domain(&mut self, domain: &str) { + self.domain = Some(domain.to_owned()); + } + + pub fn set_enable_tls(&mut self, enable_tls: bool) { + self.enable_tls = Some(enable_tls); + } + + pub fn set_enable_credssp(&mut self, enable_credssp: bool) { + self.enable_credssp = Some(enable_credssp); + } + + pub fn set_keyboard_type(&mut self, keyboard_type: KeyboardType) { + self.keyboard_type = Some(keyboard_type.into()); + } + + pub fn set_keyboard_subtype(&mut self, keyboard_subtype: u32) { + self.keyboard_subtype = Some(keyboard_subtype); + } + + pub fn set_keyboard_functional_keys_count(&mut self, keyboard_functional_keys_count: u32) { + self.keyboard_functional_keys_count = Some(keyboard_functional_keys_count); + } + + pub fn set_ime_file_name(&mut self, ime_file_name: &str) { + self.ime_file_name = Some(ime_file_name.to_owned()); + } + + pub fn set_dig_product_id(&mut self, dig_product_id: &str) { + self.dig_product_id = Some(dig_product_id.to_owned()); + } + + pub fn set_desktop_size(&mut self, height: u16, width: u16) { + self.desktop_size = Some(ironrdp::connector::DesktopSize { width, height }); + } + + pub fn set_performance_flags(&mut self, performance_flags: &PerformanceFlags) { + self.performance_flags = Some(performance_flags.0); + } + + // TODO: set bitmap + + pub fn set_client_build(&mut self, client_build: u32) { + self.client_build = Some(client_build); + } + + pub fn set_client_name(&mut self, client_name: &str) { + self.client_name = Some(client_name.to_owned()); + } + + pub fn set_client_dir(&mut self, client_dir: &str) { + self.client_dir = Some(client_dir.to_owned()); + } + + pub fn set_no_server_pointer(&mut self, no_server_pointer: bool) { + self.no_server_pointer = Some(no_server_pointer); + } + + pub fn set_autologon(&mut self, autologon: bool) { + self.autologon = Some(autologon); + } + + pub fn set_pointer_software_rendering(&mut self, pointer_software_rendering: bool) { + self.pointer_software_rendering = Some(pointer_software_rendering); + } + + pub fn build(&self) -> Result, Box> { + let inner_config = ironrdp::connector::Config { + 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), + + keyboard_type: self + .keyboard_type + .unwrap_or(ironrdp::pdu::gcc::KeyboardType::IbmEnhanced), + keyboard_subtype: self.keyboard_subtype.unwrap_or(0), + 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")?, + 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")?, + + #[cfg(windows)] + platform: MajorPlatformType::WINDOWS, + #[cfg(target_os = "macos")] + platform: MajorPlatformType::MACINTOSH, + #[cfg(target_os = "ios")] + platform: MajorPlatformType::IOS, + #[cfg(target_os = "linux")] + platform: MajorPlatformType::UNIX, + #[cfg(target_os = "android")] + platform: MajorPlatformType::ANDROID, + #[cfg(target_os = "freebsd")] + platform: MajorPlatformType::UNIX, + #[cfg(target_os = "dragonfly")] + platform: MajorPlatformType::UNIX, + #[cfg(target_os = "openbsd")] + platform: MajorPlatformType::UNIX, + #[cfg(target_os = "netbsd")] + platform: MajorPlatformType::UNIX, + + 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")?, + }; + + Ok(Box::new(Config(inner_config))) + } + } + + #[diplomat::opaque] + #[derive(Default)] + pub struct PerformanceFlags(pub ironrdp::pdu::rdp::client_info::PerformanceFlags); + + pub enum PerformanceFlagsType { + DisableWallpaper, + DisableFullWindowDrag, + DisableMenuAnimations, + DisableTheming, + Reserved1, + DisableCursorShadow, + DisableCursorSettings, + EnableFontSmoothing, + EnableDesktopComposition, + Reserved2, + } + + impl PerformanceFlags { + pub fn new_default() -> Box { + Box::::default() + } + + pub fn new_empty() -> Box { + Box::new(PerformanceFlags( + ironrdp::pdu::rdp::client_info::PerformanceFlags::empty(), + )) + } + + pub fn add_flag(&mut self, flag: PerformanceFlagsType) { + self.0.insert(flag.into()); + } + } +} + +impl From for PerformanceFlags { + fn from(val: PerformanceFlagsType) -> Self { + match val { + PerformanceFlagsType::DisableCursorSettings => PerformanceFlags::DISABLE_CURSORSETTINGS, + PerformanceFlagsType::DisableCursorShadow => PerformanceFlags::DISABLE_CURSOR_SHADOW, + PerformanceFlagsType::DisableFullWindowDrag => PerformanceFlags::DISABLE_FULLWINDOWDRAG, + PerformanceFlagsType::DisableMenuAnimations => PerformanceFlags::DISABLE_MENUANIMATIONS, + PerformanceFlagsType::DisableTheming => PerformanceFlags::DISABLE_THEMING, + PerformanceFlagsType::DisableWallpaper => PerformanceFlags::DISABLE_WALLPAPER, + PerformanceFlagsType::EnableDesktopComposition => PerformanceFlags::ENABLE_DESKTOP_COMPOSITION, + PerformanceFlagsType::EnableFontSmoothing => PerformanceFlags::ENABLE_DESKTOP_COMPOSITION, + PerformanceFlagsType::Reserved1 => PerformanceFlags::RESERVED1, + PerformanceFlagsType::Reserved2 => PerformanceFlags::RESERVED2, + } + } +} diff --git a/ffi/src/connector/mod.rs b/ffi/src/connector/mod.rs new file mode 100644 index 000000000..18b869487 --- /dev/null +++ b/ffi/src/connector/mod.rs @@ -0,0 +1,164 @@ +pub mod config; +pub mod result; +pub mod state; + +#[diplomat::bridge] +pub mod ffi { + use diplomat_runtime::DiplomatWriteable; + use ironrdp::connector::Sequence as _; + use std::fmt::Write; + + use crate::{ + error::{ + ffi::{IronRdpError, IronRdpErrorKind}, + ValueConsumedError, + }, + pdu::ffi::WriteBuf, + }; + + use super::{config::ffi::Config, result::ffi::Written}; + + #[diplomat::opaque] // We must use Option here, as ClientConnector is not Clone and have functions that consume it + pub struct ClientConnector(pub Option); + + // Basic Impl for ClientConnector + impl ClientConnector { + pub fn new(config: &Config) -> Box { + Box::new(ClientConnector(Some(ironrdp::connector::ClientConnector::new( + config.0.clone(), + )))) + } + + /// Must use + pub fn with_server_addr(&mut self, server_addr: &str) -> Result<(), Box> { + let Some(connector) = self.0.take() else { + return Err(IronRdpErrorKind::Consumed.into()); + }; + let server_addr = server_addr.parse().map_err(|_| IronRdpErrorKind::Generic)?; + self.0 = Some(connector.with_server_addr(server_addr)); + + Ok(()) + } + + // FIXME: We need to create opaque for ironrdp::svc::StaticChannelSet + /// Must use + pub fn with_static_channel_rdp_snd(&mut self) -> Result<(), Box> { + let Some(connector) = self.0.take() else { + return Err(IronRdpErrorKind::Consumed.into()); + }; + + self.0 = Some(connector.with_static_channel(ironrdp::rdpsnd::Rdpsnd::new())); + + Ok(()) + } + + // FIXME: We need to create opaque for ironrdp::rdpdr::Rdpdr + /// Must use + pub fn with_static_channel_rdpdr( + &mut self, + computer_name: &str, + smart_card_device_id: u32, + ) -> Result<(), Box> { + let Some(connector) = self.0.take() else { + return Err(ValueConsumedError::for_item("connector").into()); + }; + self.0 = Some( + connector.with_static_channel( + ironrdp::rdpdr::Rdpdr::new(Box::new(ironrdp::rdpdr::NoopRdpdrBackend {}), computer_name.to_owned()) + .with_smartcard(smart_card_device_id), + ), + ); + + Ok(()) + } + + pub fn should_perform_security_upgrade(&self) -> Result> { + let Some(connector) = self.0.as_ref() else { + return Err(ValueConsumedError::for_item("connector").into()); + }; + Ok(connector.should_perform_security_upgrade()) + } + + pub fn mark_security_upgrade_as_done(&mut self) -> Result<(), Box> { + let Some(connector) = self.0.as_mut() else { + return Err(ValueConsumedError::for_item("connector").into()); + }; + connector.mark_security_upgrade_as_done(); + Ok(()) + } + + pub fn should_perform_credssp(&self) -> Result> { + let Some(connector) = self.0.as_ref() else { + return Err(ValueConsumedError::for_item("connector").into()); + }; + + Ok(connector.should_perform_credssp()) + } + + pub fn mark_credssp_as_done(&mut self) -> Result<(), Box> { + let Some(connector) = self.0.as_mut() else { + return Err(ValueConsumedError::for_item("connector").into()); + }; + connector.mark_credssp_as_done(); + Ok(()) + } + + pub fn step(&mut self, input: &[u8], write_buf: &mut WriteBuf) -> Result, Box> { + let Some(connector) = self.0.as_mut() else { + return Err(ValueConsumedError::for_item("connector").into()); + }; + let written = connector.step(input, &mut write_buf.0)?; + Ok(Box::new(Written(written))) + } + + pub fn step_no_input(&mut self, write_buf: &mut WriteBuf) -> Result, Box> { + let Some(connector) = self.0.as_mut() else { + return Err(ValueConsumedError::for_item("connector").into()); + }; + let written = connector.step_no_input(&mut write_buf.0)?; + Ok(Box::new(Written(written))) + } + } + + #[diplomat::opaque] + pub struct PduHint<'a>(pub &'a dyn ironrdp::pdu::PduHint); + + impl<'a> PduHint<'a> { + pub fn find_size(&'a self, bytes: &[u8]) -> Result, Box> { + let pdu_hint = self.0; + let size = pdu_hint.find_size(bytes)?; + Ok(Box::new(crate::utils::ffi::OptionalUsize(size))) + } + } + + #[diplomat::opaque] + pub struct State<'a>(pub &'a dyn ironrdp::connector::State); + + impl<'a> State<'a> { + pub fn get_name(&'a self, writeable: &'a mut DiplomatWriteable) -> Result<(), Box> { + let name = self.0.name(); + write!(writeable, "{}", name)?; + Ok(()) + } + + pub fn is_terminal(&'a self) -> bool { + self.0.is_terminal() + } + } + + impl ClientConnector { + pub fn next_pdu_hint(&self) -> Result>>, Box> { + let Some(connector) = self.0.as_ref() else { + return Err(ValueConsumedError::for_item("connector").into()); + }; + Ok(connector.next_pdu_hint().map(PduHint).map(Box::new)) + } + + pub fn 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()))) + } + } +} diff --git a/ffi/src/connector/result.rs b/ffi/src/connector/result.rs new file mode 100644 index 000000000..cffea1a7b --- /dev/null +++ b/ffi/src/connector/result.rs @@ -0,0 +1,57 @@ +#[diplomat::bridge] +pub mod ffi { + use crate::{connector::config::ffi::DesktopSize, utils::ffi::OptionalUsize}; + + #[diplomat::opaque] + pub struct Written(pub ironrdp::connector::Written); + + pub enum WrittenType { + Size, + Nothing, + } + + impl Written { + pub fn get_written_type(&self) -> WrittenType { + match &self.0 { + ironrdp::connector::Written::Size(_) => WrittenType::Size, + ironrdp::connector::Written::Nothing => WrittenType::Nothing, + } + } + + pub fn get_size(&self) -> Box { + match &self.0 { + ironrdp::connector::Written::Size(size) => Box::new(OptionalUsize(Some(size.get()))), + ironrdp::connector::Written::Nothing => Box::new(OptionalUsize(None)), + } + } + } + + #[diplomat::opaque] + pub struct ConnectionResult(pub ironrdp::connector::ConnectionResult); + + impl ConnectionResult { + pub fn get_io_channel_id(&self) -> u16 { + self.0.io_channel_id + } + + pub fn get_user_channel_id(&self) -> u16 { + self.0.user_channel_id + } + + pub fn get_static_channels(&self) -> Box> { + Box::new(crate::svc::ffi::StaticChannelSet(&self.0.static_channels)) + } + + pub fn get_desktop_size(&self) -> Box { + Box::new(DesktopSize(self.0.desktop_size)) + } + + 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 + } + } +} diff --git a/ffi/src/connector/state.rs b/ffi/src/connector/state.rs new file mode 100644 index 000000000..de892368c --- /dev/null +++ b/ffi/src/connector/state.rs @@ -0,0 +1,6 @@ +#[diplomat::bridge] +pub mod ffi { + + #[diplomat::opaque] + pub struct ClientConnectorState(pub ironrdp::connector::ClientConnectorState); +} diff --git a/ffi/src/credssp/mod.rs b/ffi/src/credssp/mod.rs new file mode 100644 index 000000000..42762e195 --- /dev/null +++ b/ffi/src/credssp/mod.rs @@ -0,0 +1,101 @@ +#![allow(clippy::needless_lifetimes)] // Diplomat requires lifetimes +pub mod network; + +#[diplomat::bridge] +pub mod ffi { + + use crate::{ + connector::{ + ffi::{ClientConnector, PduHint}, + result::ffi::Written, + }, + error::{ffi::IronRdpError, ValueConsumedError}, + pdu::ffi::WriteBuf, + }; + + use super::network::ffi::{ClientState, CredsspProcessGenerator}; + + #[diplomat::opaque] + pub struct KerberosConfig(pub ironrdp::connector::credssp::KerberosConfig); + + #[diplomat::opaque] + pub struct CredsspSequence(pub ironrdp::connector::credssp::CredsspSequence); + + #[diplomat::opaque] + pub struct TsRequest(pub sspi::credssp::TsRequest); + + #[diplomat::opaque] + pub struct CredsspSequenceInitResult { + pub credssp_sequence: Option>, + pub ts_request: Option>, + } + + impl CredsspSequenceInitResult { + pub fn get_credssp_sequence(&mut self) -> Result, Box> { + let Some(credssp_sequence) = self.credssp_sequence.take() else { + return Err(ValueConsumedError::for_item("credssp_sequence").into()); + }; + Ok(credssp_sequence) + } + + pub fn get_ts_request(&mut self) -> Result, Box> { + let Some(ts_request) = self.ts_request.take() else { + return Err(ValueConsumedError::for_item("ts_request").into()); + }; + Ok(ts_request) + } + } + + impl CredsspSequence { + pub fn next_pdu_hint<'a>(&'a self) -> Option>> { + self.0.next_pdu_hint().map(|hint| Box::new(PduHint(hint))) + } + + pub fn init( + connector: &ClientConnector, + server_name: &str, + server_public_key: &[u8], + kerbero_configs: Option<&KerberosConfig>, + ) -> Result, Box> { + let Some(connector) = connector.0.as_ref() else { + return Err(ValueConsumedError::for_item("connector").into()); + }; + + let (credssp_sequence, ts_request) = ironrdp::connector::credssp::CredsspSequence::init( + connector, + server_name.into(), + server_public_key.to_owned(), + kerbero_configs.map(|config| config.0.clone()), + )?; + + Ok(Box::new(CredsspSequenceInitResult { + credssp_sequence: Some(Box::new(CredsspSequence(credssp_sequence))), + ts_request: Some(Box::new(TsRequest(ts_request))), + })) + } + + pub fn decode_server_message(&mut self, pdu: &[u8]) -> Result>, Box> { + let ts_request = self.0.decode_server_message(pdu)?; + Ok(ts_request.map(|ts_request| Box::new(TsRequest(ts_request)))) + } + + pub fn process_ts_request<'a>( + &'a mut self, + ts_request: &TsRequest, + ) -> Result>, Box> { + let ts_request = ts_request.0.clone(); + let generator = self.0.process_ts_request(ts_request); + Ok(Box::new(CredsspProcessGenerator(generator))) + } + + pub fn handle_process_result( + &mut self, + client_state: &ClientState, + buf: &mut WriteBuf, + ) -> Result, Box> { + let client_state = client_state.0.clone(); + let written = self.0.handle_process_result(client_state, &mut buf.0)?; + Ok(Box::new(Written(written))) + } + } +} diff --git a/ffi/src/credssp/network.rs b/ffi/src/credssp/network.rs new file mode 100644 index 000000000..2eb6efd79 --- /dev/null +++ b/ffi/src/credssp/network.rs @@ -0,0 +1,103 @@ +#![allow(single_use_lifetimes)] // Diplomat requires lifetimes + +pub type CredsspGeneratorState = + sspi::generator::GeneratorState>; + +#[diplomat::bridge] +pub mod ffi { + + use crate::{credssp::ffi::TsRequest, error::ffi::IronRdpError, utils::ffi::VecU8}; + + use super::CredsspGeneratorState; + + #[diplomat::opaque] + pub struct CredsspProcessGenerator<'a>(pub ironrdp::connector::credssp::CredsspProcessGenerator<'a>); + + #[diplomat::opaque] + pub struct GeneratorState(pub CredsspGeneratorState); + + #[diplomat::opaque] + pub struct NetworkRequest<'a>(pub &'a sspi::generator::NetworkRequest); + + #[diplomat::enum_convert(sspi::network_client::NetworkProtocol)] + pub enum NetworkRequestProtocol { + Tcp, + Udp, + Http, + Https, + } + + #[diplomat::opaque] + pub struct ClientState(pub sspi::credssp::ClientState); + + impl<'a> CredsspProcessGenerator<'a> { + pub fn start(&mut self) -> Result, Box> { + let state = self.0.start(); + Ok(Box::new(GeneratorState(state))) + } + + pub fn resume(&mut self, response: &[u8]) -> Result, Box> { + let state = self.0.resume(Ok(response.to_owned())); + Ok(Box::new(GeneratorState(state))) + } + } + + impl GeneratorState { + pub fn is_suspended(&self) -> bool { + matches!(self.0, CredsspGeneratorState::Suspended(_)) + } + + pub fn is_completed(&self) -> bool { + matches!(self.0, CredsspGeneratorState::Completed(_)) + } + + pub fn get_network_request_if_suspended<'a>(&'a self) -> Option>> { + match &self.0 { + CredsspGeneratorState::Suspended(request) => Some(Box::new(NetworkRequest(request))), + _ => None, + } + } + + pub fn get_client_state_if_completed(&self) -> Result, Box> { + match &self.0 { + CredsspGeneratorState::Completed(Ok(res)) => Ok(Box::new(ClientState(res.clone()))), + CredsspGeneratorState::Completed(Err(e)) => Err(e.to_owned().into()), + _ => Err("Generator is not completed".into()), + } + } + } + + impl ClientState { + pub fn is_reply_needed(&self) -> bool { + matches!(self.0, sspi::credssp::ClientState::ReplyNeeded(_)) + } + + pub fn is_final_message(&self) -> bool { + matches!(self.0, sspi::credssp::ClientState::FinalMessage(_)) + } + + pub fn get_ts_request(&self) -> Result, Box> { + match &self.0 { + sspi::credssp::ClientState::ReplyNeeded(ts_request) => Ok(Box::new(TsRequest(ts_request.clone()))), + sspi::credssp::ClientState::FinalMessage(ts_request) => Ok(Box::new(TsRequest(ts_request.clone()))), + } + } + } + + impl<'a> NetworkRequest<'a> { + pub fn get_data(&self) -> Box { + Box::new(VecU8(self.0.data.clone())) + } + + pub fn get_protocol(&self) -> NetworkRequestProtocol { + self.0.protocol.into() + } + + pub fn get_url(&self, writeable: &mut diplomat_runtime::DiplomatWriteable) -> Result<(), Box> { + use std::fmt::Write; + let url: &str = self.0.url.as_ref(); + write!(writeable, "{}", url)?; + Ok(()) + } + } +} diff --git a/ffi/src/dvc.rs b/ffi/src/dvc.rs new file mode 100644 index 000000000..1618237a1 --- /dev/null +++ b/ffi/src/dvc.rs @@ -0,0 +1,6 @@ +#[diplomat::bridge] +pub mod ffi { + + #[diplomat::opaque] + pub struct DrdynvcChannel(pub ironrdp::dvc::DrdynvcClient); +} diff --git a/ffi/src/error.rs b/ffi/src/error.rs new file mode 100644 index 000000000..3e0de3219 --- /dev/null +++ b/ffi/src/error.rs @@ -0,0 +1,138 @@ +#![allow(clippy::return_self_not_must_use)] +use std::fmt::Display; + +use ironrdp::connector::ConnectorError; + +use self::ffi::IronRdpErrorKind; + +impl From for IronRdpErrorKind { + fn from(val: ConnectorError) -> Self { + match val.kind { + ironrdp::connector::ConnectorErrorKind::Pdu(_) => IronRdpErrorKind::PduError, + ironrdp::connector::ConnectorErrorKind::Credssp(_) => IronRdpErrorKind::CredsspError, + ironrdp::connector::ConnectorErrorKind::AccessDenied => IronRdpErrorKind::AccessDenied, + _ => IronRdpErrorKind::Generic, + } + } +} + +impl From<&str> for IronRdpErrorKind { + fn from(_val: &str) -> Self { + IronRdpErrorKind::Generic + } +} + +impl From for IronRdpErrorKind { + fn from(_val: sspi::Error) -> Self { + IronRdpErrorKind::CredsspError + } +} + +impl From for IronRdpErrorKind { + fn from(_val: ironrdp::pdu::PduError) -> Self { + IronRdpErrorKind::PduError + } +} + +impl From for IronRdpErrorKind { + fn from(_: std::io::Error) -> Self { + IronRdpErrorKind::IO + } +} + +impl From for IronRdpErrorKind { + fn from(_val: std::fmt::Error) -> Self { + IronRdpErrorKind::Generic + } +} + +impl From for Box +where + T: Into + ToString, +{ + fn from(value: T) -> Self { + let repr = value.to_string(); + let kind = value.into(); + Box::new(ffi::IronRdpError(IronRdpErrorInner { repr, kind })) + } +} + +struct IronRdpErrorInner { + repr: String, + kind: IronRdpErrorKind, +} + +#[diplomat::bridge] +pub mod ffi { + use diplomat_runtime::DiplomatWriteable; + use std::fmt::Write as _; + + #[derive(Debug, Clone, Copy, thiserror::Error)] + pub enum IronRdpErrorKind { + #[error("Generic error")] + Generic, + #[error("PDU error")] + PduError, + #[error("CredSSP error")] + CredsspError, + #[error("Value is consumed")] + Consumed, + #[error("IO error")] + IO, + #[error("Access denied")] + AccessDenied, + } + + /// Stringified Picky error along with an error kind. + #[diplomat::opaque] + pub struct IronRdpError(pub(super) super::IronRdpErrorInner); + + impl IronRdpError { + /// Returns the error as a string. + pub fn to_display(&self, writeable: &mut DiplomatWriteable) { + let _ = write!(writeable, "{}", self.0.repr); + writeable.flush(); + } + + /// Returns the error kind. + pub fn get_kind(&self) -> IronRdpErrorKind { + self.0.kind + } + } +} + +#[derive(Debug)] +pub struct ValueConsumedError { + item: String, + reason: Option, +} + +impl ValueConsumedError { + pub fn for_item(item: &str) -> ValueConsumedError { + ValueConsumedError { + item: item.to_owned(), + reason: None, + } + } + + pub fn reason(mut self, reason: &str) -> ValueConsumedError { + self.reason = Some(reason.to_owned()); + self + } +} + +impl Display for ValueConsumedError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if let Some(reason) = &self.reason { + write!(f, "{}: {}", self.item, reason) + } else { + write!(f, "{}: is consumed or never constructed", self.item) + } + } +} + +impl From for IronRdpErrorKind { + fn from(_val: ValueConsumedError) -> Self { + IronRdpErrorKind::Consumed + } +} diff --git a/ffi/src/lib.rs b/ffi/src/lib.rs new file mode 100644 index 000000000..d8884366b --- /dev/null +++ b/ffi/src/lib.rs @@ -0,0 +1,9 @@ +#![allow(clippy::unnecessary_box_returns)] // Diplomat requires returning Boxed types + +pub mod connector; +pub mod credssp; +pub mod dvc; +pub mod error; +pub mod pdu; +pub mod svc; +pub mod utils; diff --git a/ffi/src/pdu.rs b/ffi/src/pdu.rs new file mode 100644 index 000000000..a7f887e6f --- /dev/null +++ b/ffi/src/pdu.rs @@ -0,0 +1,23 @@ +#[diplomat::bridge] +pub mod ffi { + + use crate::error::ffi::IronRdpError; + + #[diplomat::opaque] + pub struct WriteBuf(pub ironrdp::pdu::write_buf::WriteBuf); + + impl WriteBuf { + pub fn new() -> Box { + Box::new(WriteBuf(ironrdp::pdu::write_buf::WriteBuf::new())) + } + + pub fn clear(&mut self) { + self.0.clear(); + } + + pub fn read_into_buf(&mut self, buf: &mut [u8]) -> Result<(), Box> { + buf.copy_from_slice(&self.0[..buf.len()]); + Ok(()) + } + } +} diff --git a/ffi/src/svc.rs b/ffi/src/svc.rs new file mode 100644 index 000000000..87e083bbd --- /dev/null +++ b/ffi/src/svc.rs @@ -0,0 +1,6 @@ +#[diplomat::bridge] +pub mod ffi { + + #[diplomat::opaque] + pub struct StaticChannelSet<'a>(pub &'a ironrdp::svc::StaticChannelSet); +} diff --git a/ffi/src/utils/mod.rs b/ffi/src/utils/mod.rs new file mode 100644 index 000000000..6ede3dae6 --- /dev/null +++ b/ffi/src/utils/mod.rs @@ -0,0 +1,43 @@ +#[diplomat::bridge] +pub mod ffi { + + use crate::error::ffi::IronRdpError; + + #[diplomat::opaque] + pub struct VecU8(pub Vec); + + impl VecU8 { + pub fn from_bytes(bytes: &[u8]) -> Box { + Box::new(VecU8(bytes.to_vec())) + } + + pub fn get_size(&self) -> usize { + self.0.len() + } + + pub fn fill(&self, buffer: &mut [u8]) -> Result<(), Box> { + if buffer.len() < self.0.len() { + return Err("Buffer is too small".into()); + } + buffer.copy_from_slice(&self.0); + Ok(()) + } + + pub fn new_empty() -> Box { + Box::new(VecU8(Vec::new())) + } + } + + #[diplomat::opaque] + pub struct OptionalUsize(pub Option); + + impl OptionalUsize { + pub fn is_some(&self) -> bool { + self.0.is_some() + } + + pub fn get(&self) -> Result> { + self.0.ok_or_else(|| "Value is None".into()) + } + } +} diff --git a/xtask/src/cli.rs b/xtask/src/cli.rs index 331eba208..fc8a0f854 100644 --- a/xtask/src/cli.rs +++ b/xtask/src/cli.rs @@ -36,6 +36,9 @@ TASKS: web check Ensure Web Client is building without error web install Install dependencies required to build and run Web Client web run Run SvelteKit-based standalone Web Client + ffi build [--release] Build DLL for FFI (default is debug) + ffi bindings [--skip-dotnet-build] + Generate C# bindings for FFI, optionally skipping the .NET build "; pub fn print_help() { @@ -85,6 +88,12 @@ pub enum Action { WebCheck, WebInstall, WebRun, + FfiBuildDll { + release: bool, + }, + FfiBuildBindings { + skip_dotnet_build: bool, + }, } pub fn parse_args() -> anyhow::Result { @@ -152,6 +161,16 @@ pub fn parse_args() -> anyhow::Result { Some(unknown) => anyhow::bail!("unknown web action: {unknown}"), None => Action::ShowHelp, }, + Some("ffi") => match args.subcommand()?.as_deref() { + Some("build") => Action::FfiBuildDll { + release: args.contains("--release"), + }, + Some("bindings") => Action::FfiBuildBindings { + skip_dotnet_build: args.contains("--skip-dotnet-build"), + }, + Some(unknown) => anyhow::bail!("unknown ffi action: {unknown}"), + None => Action::ShowHelp, + }, None | Some(_) => Action::ShowHelp, } }; diff --git a/xtask/src/ffi.rs b/xtask/src/ffi.rs new file mode 100644 index 000000000..8406dd624 --- /dev/null +++ b/xtask/src/ffi.rs @@ -0,0 +1,78 @@ +pub(crate) fn build_dll(sh: &xshell::Shell, release: bool) -> anyhow::Result<()> { + let mut args = vec!["build", "--package", "ffi"]; + if release { + args.push("--release"); + } + sh.cmd("cargo").args(&args).run()?; + + let target_dir = if release { "release" } else { "debug" }; + + let mut path = sh.current_dir(); + path.push("target"); + path.push(target_dir); + + let dll_name = "ironrdp.dll"; + let devolution_dll_name = "DevolutionsIronRdp.dll"; + + let mut dll_path = path.clone(); + dll_path.push(dll_name); + + let mut devolution_dll_path = path.clone(); + devolution_dll_path.push(devolution_dll_name); + + // copy dll_path to devolution_dll_path + std::fs::copy(&dll_path, &devolution_dll_path)?; + println!("Copied {:?} to {:?}", dll_path, devolution_dll_path); + + Ok(()) +} + +use std::fs; +use std::path::Path; + +pub(crate) fn build_bindings(sh: &xshell::Shell, skip_dotnet_build: bool) -> anyhow::Result<()> { + let dotnet_generated_path = "./dotnet/Devolutions.IronRdp/Generated/"; + let diplomat_config = "./dotnet-interop-conf.toml"; + + // Check if diplomat tool is installed + sh.change_dir("./ffi"); + let cwd = sh.current_dir(); + let generated_code_dir = cwd.join(dotnet_generated_path); + if !generated_code_dir.exists() { + anyhow::bail!("The directory {:?} does not exist", generated_code_dir); + } + remove_cs_files(&generated_code_dir)?; + + sh.cmd("diplomat-tool") + .arg("dotnet") + .arg(dotnet_generated_path) + .arg("-l") + .arg(diplomat_config) + .run()?; + + if skip_dotnet_build { + return Ok(()); + } + + sh.change_dir("./dotnet"); + sh.change_dir("./Devolutions.IronRdp"); + + sh.cmd("dotnet").arg("build").run()?; + + Ok(()) +} + +/// Removes all `.cs` files in the given directory. +fn remove_cs_files(dir: &Path) -> anyhow::Result<()> { + if dir.is_dir() { + for entry in fs::read_dir(dir)? { + let entry = entry?; + let path = entry.path(); + if path.is_file() && path.extension().and_then(|s| s.to_str()) == Some("cs") { + println!("Removing file: {:?}", path); + fs::remove_file(path)?; + } + } + } + Ok(()) +} diff --git a/xtask/src/main.rs b/xtask/src/main.rs index d420de90b..781700f94 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -12,6 +12,7 @@ mod check; mod clean; mod cli; mod cov; +mod ffi; mod fuzz; mod prelude; mod section; @@ -111,6 +112,8 @@ fn main() -> anyhow::Result<()> { Action::WebCheck => web::check(&sh)?, Action::WebInstall => web::install(&sh)?, Action::WebRun => web::run(&sh)?, + Action::FfiBuildDll { release: debug } => ffi::build_dll(&sh, debug)?, + Action::FfiBuildBindings { skip_dotnet_build } => ffi::build_bindings(&sh, skip_dotnet_build)?, } Ok(())