feat(ffi): expose cliprdr to dotnet bindings (#459)

This commit is contained in:
irvingouj @ Devolutions
2024-05-14 07:07:34 +00:00
committed by GitHub
parent e24fb56275
commit 579823a1a9
42 changed files with 1844 additions and 66 deletions
Generated
+2
View File
@@ -1134,10 +1134,12 @@ dependencies = [
"diplomat-runtime",
"embed-resource",
"ironrdp",
"ironrdp-cliprdr-native",
"sspi",
"thiserror",
"tracing",
"tracing-subscriber",
"windows 0.48.0",
]
[[package]]
+7 -1
View File
@@ -19,7 +19,8 @@ doctest = false
[dependencies]
diplomat = "0.7.0"
diplomat-runtime = "0.7.0"
ironrdp = { workspace = true, features = ["connector", "dvc", "svc","rdpdr","rdpsnd","graphics","input"] }
ironrdp = { workspace = true, features = ["connector", "dvc", "svc","rdpdr","rdpsnd","graphics","input","cliprdr"] }
ironrdp-cliprdr-native = { workspace = true }
sspi = { workspace = true, features = ["network_client"] }
thiserror.workspace = true
tracing.workspace = true
@@ -27,3 +28,8 @@ tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
[target.'cfg(windows)'.build-dependencies]
embed-resource = "2.2.0"
[target.'cfg(windows)'.dependencies]
windows = { version = "0.48", features = [
"Win32_Foundation",
] }
@@ -9,13 +9,22 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.0.10" />
<PackageReference Include="Avalonia.Desktop" Version="11.0.10" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.10" />
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.0.10" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<!--Condition
below is needed to remove Avalonia.Diagnostics package from build output in Release
configuration.-->
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.10" />
<ProjectReference Include="../Devolutions.IronRdp/Devolutions.IronRdp.csproj" />
</ItemGroup>
</Project>
<ItemGroup Condition="'$([System.OperatingSystem]::IsWindows())'">
<PackageReference Include="Avalonia.Win32" Version="11.0.10" />
</ItemGroup>
</Project>
@@ -7,25 +7,32 @@ using Avalonia.Threading;
using System;
using System.Diagnostics;
using System.Net.Security;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Avalonia.Markup.Xaml;
namespace Devolutions.IronRdp.AvaloniaExample;
public partial class MainWindow : Window
{
WriteableBitmap? _bitmap;
Canvas? _canvas;
Image? _image;
readonly InputDatabase? _inputDatabase = InputDatabase.New();
ActiveStage? _activeStage;
DecodedImage? _decodedImage;
Framed<SslStream>? _framed;
WinCliprdr? _cliprdr;
WriteableBitmap? bitmap;
Canvas? canvas;
Image? image;
InputDatabase? inputDatabase = InputDatabase.New();
ActiveStage? activeStage;
DecodedImage? decodedImage;
Framed<SslStream>? framed;
public MainWindow()
{
InitializeComponent();
this.Opened += OnOpened;
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
private void OnOpened(object? sender, EventArgs e)
@@ -41,54 +48,84 @@ public partial class MainWindow : Window
if (username == null || password == null || domain == null || server == null)
{
Trace.TraceError("Please set the IRONRDP_USERNAME, IRONRDP_PASSWORD, IRONRDP_DOMAIN, and IRONRDP_SERVER environment variables");
Trace.TraceError(
"Please set the IRONRDP_USERNAME, IRONRDP_PASSWORD, IRONRDP_DOMAIN, and IRONRDP_SERVER environment variables");
Close();
return;
}
var width = 1280;
var height = 800;
const int width = 1280;
const int height = 800;
var config = buildConfig(username, password, domain, width, height);
var config = BuildConfig(username, password, domain, width, height);
var task = Connection.Connect(config, server);
bitmap = new WriteableBitmap(new PixelSize(width, height), new Vector(96, 96), Avalonia.Platform.PixelFormat.Rgba8888, AlphaFormat.Opaque);
canvas = this.FindControl<Canvas>("MainCanvas")!;
canvas.Focusable = true;
image = new Image { Width = width, Height = height, Source = this.bitmap };
canvas.Children.Add(image);
CliprdrBackendFactory? factory = null;
var handle = GetWindowHandle();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && handle != null)
{
_cliprdr = WinCliprdr.New(handle.Value);
if (_cliprdr != null)
{
factory = _cliprdr.BackendFactory();
}
}
canvas.KeyDown += Canvas_KeyDown;
canvas.KeyUp += Canvas_KeyUp;
var task = Connection.Connect(config, server, factory);
PostConnectSetup(width, height);
task.ContinueWith(t =>
{
if (t.IsFaulted)
{
Exception e = t.Exception!;
Trace.TraceError("Error connecting to server: " + e.Message);
Exception connectError = t.Exception!;
Trace.TraceError("Error connecting to server: " + connectError.Message);
Close();
return;
}
var (res, framed) = t.Result;
this.decodedImage = DecodedImage.New(PixelFormat.RgbA32, res.GetDesktopSize().GetWidth(), res.GetDesktopSize().GetHeight());
this.activeStage = ActiveStage.New(res);
this.framed = framed;
this._decodedImage = DecodedImage.New(PixelFormat.RgbA32, res.GetDesktopSize().GetWidth(),
res.GetDesktopSize().GetHeight());
this._activeStage = ActiveStage.New(res);
this._framed = framed;
ReadPduAndProcessActiveStage();
HandleClipboardEvents();
}).ContinueWith(t =>
{
if (t.IsFaulted)
{
Trace.TraceError("Error processing active stage: " + t.Exception!.Message);
Close();
}
return;
});
}
private void PostConnectSetup(int width, int height)
{
_bitmap = new WriteableBitmap(new PixelSize(width, height), new Vector(96, 96),
Avalonia.Platform.PixelFormat.Rgba8888, AlphaFormat.Opaque);
_canvas = this.FindControl<Canvas>("MainCanvas")!;
_canvas.Focusable = true;
_image = new Image { Width = width, Height = height, Source = this._bitmap };
_canvas.Children.Add(_image);
_canvas.KeyDown += Canvas_KeyDown;
_canvas.KeyUp += Canvas_KeyUp;
}
private async void WriteDecodedImageToCanvas()
{
await Dispatcher.UIThread.InvokeAsync(() =>
{
var data = decodedImage!.GetData();
var data = _decodedImage!.GetData();
var bufferSize = (int)data.GetSize();
var buffer = new byte[bufferSize];
data.Fill(buffer);
using (var bitmap = this.bitmap!.Lock())
using (var bitmap = this._bitmap!.Lock())
{
unsafe
{
@@ -98,13 +135,10 @@ public partial class MainWindow : Window
}
}
image!.InvalidateVisual();
_image!.InvalidateVisual();
});
}
private void ReadPduAndProcessActiveStage()
{
Task.Run(async () =>
@@ -112,16 +146,61 @@ public partial class MainWindow : Window
var keepLooping = true;
while (keepLooping)
{
var readPduTask = await framed!.ReadPdu();
var readPduTask = await _framed!.ReadPdu();
Action action = readPduTask.Item1;
byte[] payload = readPduTask.Item2;
var outputIterator = activeStage!.Process(decodedImage!, action, payload);
var outputIterator = _activeStage!.Process(_decodedImage!, action, payload);
keepLooping = await HandleActiveStageOutput(outputIterator);
}
});
}
private static Config buildConfig(string username, string password, string domain, int width, int height)
private void HandleClipboardEvents()
{
Task.Run(async () =>
{
while (true)
{
if (_cliprdr == null)
{
continue;
}
var message = _cliprdr.NextClipboardMessageBlocking();
VecU8 frame;
var messageType = message.GetMessageType();
Trace.TraceInformation("Clipboard message type: " + messageType);
if (messageType == ClipboardMessageType.SendFormatData)
{
var formatData = message.GetSendFormatData()!;
frame = _activeStage!.SubmitClipboardFormatData(formatData);
}
else if (messageType == ClipboardMessageType.SendInitiateCopy)
{
var initiateCopy = message.GetSendInitiateCopy()!;
frame = _activeStage!.InitiateClipboardCopy(initiateCopy);
}
else if (messageType == ClipboardMessageType.SendInitiatePaste)
{
var initiatePaste = message.GetSendInitiatePaste()!;
frame = _activeStage!.InitiateClipboardPaste(initiatePaste);
}
else
{
Console.WriteLine("Error in clipboard");
break;
}
var toWriteBack = new byte[frame.GetSize()];
frame.Fill(toWriteBack);
await _framed!.Write(toWriteBack);
}
});
}
private static Config BuildConfig(string username, string password, string domain, int width, int height)
{
ConfigBuilder configBuilder = ConfigBuilder.New();
@@ -135,7 +214,7 @@ public partial class MainWindow : Window
return configBuilder.Build();
}
private void Canvas_OnPointerPressed(object sender, Avalonia.Input.PointerPressedEventArgs e)
private void Canvas_OnPointerPressed(object sender, PointerPressedEventArgs e)
{
PointerUpdateKind mouseButton = e.GetCurrentPoint((Visual?)sender).Properties.PointerUpdateKind;
@@ -156,23 +235,24 @@ public partial class MainWindow : Window
};
var buttonOperation = MouseButton.New(buttonType).AsOperationMouseButtonPressed();
var fastpath = inputDatabase!.Apply(buttonOperation);
var output = activeStage!.ProcessFastpathInput(decodedImage!, fastpath);
var fastpath = _inputDatabase!.Apply(buttonOperation);
var output = _activeStage!.ProcessFastpathInput(_decodedImage!, fastpath);
var _ = HandleActiveStageOutput(output);
}
private void Canvas_PointerMoved(object sender, PointerEventArgs e)
{
if (this.activeStage == null || this.decodedImage == null)
if (this._activeStage == null || this._decodedImage == null)
{
return;
}
var position = e.GetPosition((Visual?)sender);
var x = (ushort)position.X;
var y = (ushort)position.Y;
var mouseMovedEvent = MousePosition.New(x, y).AsMoveOperation();
var fastpath = inputDatabase!.Apply(mouseMovedEvent);
var output = activeStage.ProcessFastpathInput(decodedImage, fastpath);
var fastpath = _inputDatabase!.Apply(mouseMovedEvent);
var output = _activeStage.ProcessFastpathInput(_decodedImage, fastpath);
var _ = HandleActiveStageOutput(output);
}
@@ -197,35 +277,37 @@ public partial class MainWindow : Window
};
var buttonOperation = MouseButton.New(buttonType).AsOperationMouseButtonReleased();
var fastpath = inputDatabase!.Apply(buttonOperation);
var output = activeStage!.ProcessFastpathInput(decodedImage!, fastpath);
var fastpath = _inputDatabase!.Apply(buttonOperation);
var output = _activeStage!.ProcessFastpathInput(_decodedImage!, fastpath);
var _ = HandleActiveStageOutput(output);
}
private void Canvas_KeyDown(object? sender, KeyEventArgs? e)
{
if (activeStage == null || decodedImage == null)
if (_activeStage == null || _decodedImage == null)
{
return;
}
PhysicalKey physicalKey = e!.PhysicalKey;
var keyOperation = Scancode.FromU16((ushort)KeyCodeMapper.GetScancode(physicalKey)!).AsOperationKeyPressed();
var fastpath = inputDatabase!.Apply(keyOperation);
var output = activeStage.ProcessFastpathInput(decodedImage, fastpath);
var fastpath = _inputDatabase!.Apply(keyOperation);
var output = _activeStage.ProcessFastpathInput(_decodedImage, fastpath);
var _ = HandleActiveStageOutput(output);
}
private void Canvas_KeyUp(object? sender, KeyEventArgs? e)
{
if (this.activeStage == null || this.decodedImage == null)
if (this._activeStage == null || this._decodedImage == null)
{
return;
}
Key key = e!.Key;
var keyOperation = Scancode.FromU16((ushort)key).AsOperationKeyReleased();
var fastpath = inputDatabase!.Apply(keyOperation);
var output = activeStage.ProcessFastpathInput(decodedImage, fastpath);
var fastpath = _inputDatabase!.Apply(keyOperation);
var output = _activeStage.ProcessFastpathInput(_decodedImage, fastpath);
var _ = HandleActiveStageOutput(output);
}
@@ -233,10 +315,10 @@ public partial class MainWindow : Window
{
try
{
while (!outputIterator.IsEmpty())
{
var output = outputIterator.Next()!; // outputIterator.Next() is not null since outputIterator.IsEmpty() is false
var output =
outputIterator.Next()!; // outputIterator.Next() is not null since outputIterator.IsEmpty() is false
if (output.GetEnumType() == ActiveStageOutputType.Terminate)
{
return false;
@@ -246,10 +328,10 @@ public partial class MainWindow : Window
// render the decoded image to canvas
WriteDecodedImageToCanvas();
// Send the response frame to the server
var responseFrame = output.GetResponseFrame()!;
var responseFrame = output.GetResponseFrame();
byte[] responseFrameBytes = new byte[responseFrame.GetSize()];
responseFrame.Fill(responseFrameBytes);
await framed!.Write(responseFrameBytes);
await _framed!.Write(responseFrameBytes);
}
else if (output.GetEnumType() == ActiveStageOutputType.GraphicsUpdate)
{
@@ -264,12 +346,23 @@ public partial class MainWindow : Window
WriteDecodedImageToCanvas();
}
}
return true;
}
catch (Exception e)
catch (Exception)
{
return false;
}
}
}
IntPtr? GetWindowHandle()
{
var handle = this.TryGetPlatformHandle();
if (handle == null)
{
return null;
}
return handle.Handle;
}
}
@@ -125,6 +125,90 @@ public partial class ActiveStage: IDisposable
}
}
/// <exception cref="IronRdpException"></exception>
/// <returns>
/// A <c>VecU8</c> allocated on Rust side.
/// </returns>
public VecU8 InitiateClipboardCopy(ClipboardFormatIterator formats)
{
unsafe
{
if (_inner == null)
{
throw new ObjectDisposedException("ActiveStage");
}
Raw.ClipboardFormatIterator* formatsRaw;
formatsRaw = formats.AsFFI();
if (formatsRaw == null)
{
throw new ObjectDisposedException("ClipboardFormatIterator");
}
Raw.SessionFfiResultBoxVecU8BoxIronRdpError result = Raw.ActiveStage.InitiateClipboardCopy(_inner, formatsRaw);
if (!result.isOk)
{
throw new IronRdpException(new IronRdpError(result.Err));
}
Raw.VecU8* retVal = result.Ok;
return new VecU8(retVal);
}
}
/// <exception cref="IronRdpException"></exception>
/// <returns>
/// A <c>VecU8</c> allocated on Rust side.
/// </returns>
public VecU8 InitiateClipboardPaste(ClipboardFormatId formatId)
{
unsafe
{
if (_inner == null)
{
throw new ObjectDisposedException("ActiveStage");
}
Raw.ClipboardFormatId* formatIdRaw;
formatIdRaw = formatId.AsFFI();
if (formatIdRaw == null)
{
throw new ObjectDisposedException("ClipboardFormatId");
}
Raw.SessionFfiResultBoxVecU8BoxIronRdpError result = Raw.ActiveStage.InitiateClipboardPaste(_inner, formatIdRaw);
if (!result.isOk)
{
throw new IronRdpException(new IronRdpError(result.Err));
}
Raw.VecU8* retVal = result.Ok;
return new VecU8(retVal);
}
}
/// <exception cref="IronRdpException"></exception>
/// <returns>
/// A <c>VecU8</c> allocated on Rust side.
/// </returns>
public VecU8 SubmitClipboardFormatData(FormatDataResponse formatDataResponse)
{
unsafe
{
if (_inner == null)
{
throw new ObjectDisposedException("ActiveStage");
}
Raw.FormatDataResponse* formatDataResponseRaw;
formatDataResponseRaw = formatDataResponse.AsFFI();
if (formatDataResponseRaw == null)
{
throw new ObjectDisposedException("FormatDataResponse");
}
Raw.SessionFfiResultBoxVecU8BoxIronRdpError result = Raw.ActiveStage.SubmitClipboardFormatData(_inner, formatDataResponseRaw);
if (!result.isOk)
{
throw new IronRdpException(new IronRdpError(result.Err));
}
Raw.VecU8* retVal = result.Ok;
return new VecU8(retVal);
}
}
/// <summary>
/// Returns the underlying raw handle.
/// </summary>
@@ -257,6 +257,29 @@ public partial class ClientConnector: IDisposable
}
}
/// <exception cref="IronRdpException"></exception>
public void AttachStaticCliprdr(Cliprdr cliprdr)
{
unsafe
{
if (_inner == null)
{
throw new ObjectDisposedException("ClientConnector");
}
Raw.Cliprdr* cliprdrRaw;
cliprdrRaw = cliprdr.AsFFI();
if (cliprdrRaw == null)
{
throw new ObjectDisposedException("Cliprdr");
}
Raw.ConnectorFfiResultVoidBoxIronRdpError result = Raw.ClientConnector.AttachStaticCliprdr(_inner, cliprdrRaw);
if (!result.isOk)
{
throw new IronRdpException(new IronRdpError(result.Err));
}
}
}
/// <exception cref="IronRdpException"></exception>
/// <returns>
/// A <c>PduHint</c> allocated on Rust side.
@@ -0,0 +1,63 @@
// <auto-generated/> 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 ClipboardFormatId: IDisposable
{
private unsafe Raw.ClipboardFormatId* _inner;
/// <summary>
/// Creates a managed <c>ClipboardFormatId</c> from a raw handle.
/// </summary>
/// <remarks>
/// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free).
/// <br/>
/// This constructor assumes the raw struct is allocated on Rust side.
/// If implemented, the custom Drop implementation on Rust side WILL run on destruction.
/// </remarks>
public unsafe ClipboardFormatId(Raw.ClipboardFormatId* handle)
{
_inner = handle;
}
/// <summary>
/// Returns the underlying raw handle.
/// </summary>
public unsafe Raw.ClipboardFormatId* AsFFI()
{
return _inner;
}
/// <summary>
/// Destroys the underlying object immediately.
/// </summary>
public void Dispose()
{
unsafe
{
if (_inner == null)
{
return;
}
Raw.ClipboardFormatId.Destroy(_inner);
_inner = null;
GC.SuppressFinalize(this);
}
}
~ClipboardFormatId()
{
Dispose();
}
}
@@ -0,0 +1,63 @@
// <auto-generated/> 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 ClipboardFormatIterator: IDisposable
{
private unsafe Raw.ClipboardFormatIterator* _inner;
/// <summary>
/// Creates a managed <c>ClipboardFormatIterator</c> from a raw handle.
/// </summary>
/// <remarks>
/// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free).
/// <br/>
/// This constructor assumes the raw struct is allocated on Rust side.
/// If implemented, the custom Drop implementation on Rust side WILL run on destruction.
/// </remarks>
public unsafe ClipboardFormatIterator(Raw.ClipboardFormatIterator* handle)
{
_inner = handle;
}
/// <summary>
/// Returns the underlying raw handle.
/// </summary>
public unsafe Raw.ClipboardFormatIterator* AsFFI()
{
return _inner;
}
/// <summary>
/// Destroys the underlying object immediately.
/// </summary>
public void Dispose()
{
unsafe
{
if (_inner == null)
{
return;
}
Raw.ClipboardFormatIterator.Destroy(_inner);
_inner = null;
GC.SuppressFinalize(this);
}
}
~ClipboardFormatIterator()
{
Dispose();
}
}
@@ -0,0 +1,171 @@
// <auto-generated/> 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 ClipboardMessage: IDisposable
{
private unsafe Raw.ClipboardMessage* _inner;
public ClipboardMessageType MessageType
{
get
{
return GetMessageType();
}
}
public FormatDataResponse? SendFormatData
{
get
{
return GetSendFormatData();
}
}
public ClipboardFormatIterator? SendInitiateCopy
{
get
{
return GetSendInitiateCopy();
}
}
public ClipboardFormatId? SendInitiatePaste
{
get
{
return GetSendInitiatePaste();
}
}
/// <summary>
/// Creates a managed <c>ClipboardMessage</c> from a raw handle.
/// </summary>
/// <remarks>
/// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free).
/// <br/>
/// This constructor assumes the raw struct is allocated on Rust side.
/// If implemented, the custom Drop implementation on Rust side WILL run on destruction.
/// </remarks>
public unsafe ClipboardMessage(Raw.ClipboardMessage* handle)
{
_inner = handle;
}
/// <returns>
/// A <c>ClipboardMessageType</c> allocated on C# side.
/// </returns>
public ClipboardMessageType GetMessageType()
{
unsafe
{
if (_inner == null)
{
throw new ObjectDisposedException("ClipboardMessage");
}
Raw.ClipboardMessageType retVal = Raw.ClipboardMessage.GetMessageType(_inner);
return (ClipboardMessageType)retVal;
}
}
/// <returns>
/// A <c>ClipboardFormatIterator</c> allocated on Rust side.
/// </returns>
public ClipboardFormatIterator? GetSendInitiateCopy()
{
unsafe
{
if (_inner == null)
{
throw new ObjectDisposedException("ClipboardMessage");
}
Raw.ClipboardFormatIterator* retVal = Raw.ClipboardMessage.GetSendInitiateCopy(_inner);
if (retVal == null)
{
return null;
}
return new ClipboardFormatIterator(retVal);
}
}
/// <returns>
/// A <c>FormatDataResponse</c> allocated on Rust side.
/// </returns>
public FormatDataResponse? GetSendFormatData()
{
unsafe
{
if (_inner == null)
{
throw new ObjectDisposedException("ClipboardMessage");
}
Raw.FormatDataResponse* retVal = Raw.ClipboardMessage.GetSendFormatData(_inner);
if (retVal == null)
{
return null;
}
return new FormatDataResponse(retVal);
}
}
/// <returns>
/// A <c>ClipboardFormatId</c> allocated on Rust side.
/// </returns>
public ClipboardFormatId? GetSendInitiatePaste()
{
unsafe
{
if (_inner == null)
{
throw new ObjectDisposedException("ClipboardMessage");
}
Raw.ClipboardFormatId* retVal = Raw.ClipboardMessage.GetSendInitiatePaste(_inner);
if (retVal == null)
{
return null;
}
return new ClipboardFormatId(retVal);
}
}
/// <summary>
/// Returns the underlying raw handle.
/// </summary>
public unsafe Raw.ClipboardMessage* AsFFI()
{
return _inner;
}
/// <summary>
/// Destroys the underlying object immediately.
/// </summary>
public void Dispose()
{
unsafe
{
if (_inner == null)
{
return;
}
Raw.ClipboardMessage.Destroy(_inner);
_inner = null;
GC.SuppressFinalize(this);
}
}
~ClipboardMessage()
{
Dispose();
}
}
@@ -0,0 +1,20 @@
// <auto-generated/> 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 ClipboardMessageType
{
SendInitiateCopy = 0,
SendFormatData = 1,
SendInitiatePaste = 2,
Error = 3,
}
@@ -0,0 +1,63 @@
// <auto-generated/> 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 ClipboardSvgMessage: IDisposable
{
private unsafe Raw.ClipboardSvgMessage* _inner;
/// <summary>
/// Creates a managed <c>ClipboardSvgMessage</c> from a raw handle.
/// </summary>
/// <remarks>
/// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free).
/// <br/>
/// This constructor assumes the raw struct is allocated on Rust side.
/// If implemented, the custom Drop implementation on Rust side WILL run on destruction.
/// </remarks>
public unsafe ClipboardSvgMessage(Raw.ClipboardSvgMessage* handle)
{
_inner = handle;
}
/// <summary>
/// Returns the underlying raw handle.
/// </summary>
public unsafe Raw.ClipboardSvgMessage* AsFFI()
{
return _inner;
}
/// <summary>
/// Destroys the underlying object immediately.
/// </summary>
public void Dispose()
{
unsafe
{
if (_inner == null)
{
return;
}
Raw.ClipboardSvgMessage.Destroy(_inner);
_inner = null;
GC.SuppressFinalize(this);
}
}
~ClipboardSvgMessage()
{
Dispose();
}
}
@@ -0,0 +1,63 @@
// <auto-generated/> 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 Cliprdr: IDisposable
{
private unsafe Raw.Cliprdr* _inner;
/// <summary>
/// Creates a managed <c>Cliprdr</c> from a raw handle.
/// </summary>
/// <remarks>
/// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free).
/// <br/>
/// This constructor assumes the raw struct is allocated on Rust side.
/// If implemented, the custom Drop implementation on Rust side WILL run on destruction.
/// </remarks>
public unsafe Cliprdr(Raw.Cliprdr* handle)
{
_inner = handle;
}
/// <summary>
/// Returns the underlying raw handle.
/// </summary>
public unsafe Raw.Cliprdr* AsFFI()
{
return _inner;
}
/// <summary>
/// Destroys the underlying object immediately.
/// </summary>
public void Dispose()
{
unsafe
{
if (_inner == null)
{
return;
}
Raw.Cliprdr.Destroy(_inner);
_inner = null;
GC.SuppressFinalize(this);
}
}
~Cliprdr()
{
Dispose();
}
}
@@ -0,0 +1,79 @@
// <auto-generated/> 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 CliprdrBackendFactory: IDisposable
{
private unsafe Raw.CliprdrBackendFactory* _inner;
/// <summary>
/// Creates a managed <c>CliprdrBackendFactory</c> from a raw handle.
/// </summary>
/// <remarks>
/// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free).
/// <br/>
/// This constructor assumes the raw struct is allocated on Rust side.
/// If implemented, the custom Drop implementation on Rust side WILL run on destruction.
/// </remarks>
public unsafe CliprdrBackendFactory(Raw.CliprdrBackendFactory* handle)
{
_inner = handle;
}
/// <returns>
/// A <c>Cliprdr</c> allocated on Rust side.
/// </returns>
public Cliprdr BuildCliprdr()
{
unsafe
{
if (_inner == null)
{
throw new ObjectDisposedException("CliprdrBackendFactory");
}
Raw.Cliprdr* retVal = Raw.CliprdrBackendFactory.BuildCliprdr(_inner);
return new Cliprdr(retVal);
}
}
/// <summary>
/// Returns the underlying raw handle.
/// </summary>
public unsafe Raw.CliprdrBackendFactory* AsFFI()
{
return _inner;
}
/// <summary>
/// Destroys the underlying object immediately.
/// </summary>
public void Dispose()
{
unsafe
{
if (_inner == null)
{
return;
}
Raw.CliprdrBackendFactory.Destroy(_inner);
_inner = null;
GC.SuppressFinalize(this);
}
}
~CliprdrBackendFactory()
{
Dispose();
}
}
@@ -0,0 +1,63 @@
// <auto-generated/> 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 FormatDataResponse: IDisposable
{
private unsafe Raw.FormatDataResponse* _inner;
/// <summary>
/// Creates a managed <c>FormatDataResponse</c> from a raw handle.
/// </summary>
/// <remarks>
/// Safety: you should not build two managed objects using the same raw handle (may causes use-after-free and double-free).
/// <br/>
/// This constructor assumes the raw struct is allocated on Rust side.
/// If implemented, the custom Drop implementation on Rust side WILL run on destruction.
/// </remarks>
public unsafe FormatDataResponse(Raw.FormatDataResponse* handle)
{
_inner = handle;
}
/// <summary>
/// Returns the underlying raw handle.
/// </summary>
public unsafe Raw.FormatDataResponse* AsFFI()
{
return _inner;
}
/// <summary>
/// Destroys the underlying object immediately.
/// </summary>
public void Dispose()
{
unsafe
{
if (_inner == null)
{
return;
}
Raw.FormatDataResponse.Destroy(_inner);
_inner = null;
GC.SuppressFinalize(this);
}
}
~FormatDataResponse()
{
Dispose();
}
}
@@ -20,4 +20,6 @@ public enum IronRdpErrorKind
IO = 4,
AccessDenied = 5,
IncorrectEnumType = 6,
Clipboard = 7,
WrongOS = 8,
}
@@ -25,6 +25,15 @@ public partial struct ActiveStage
[DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStage_process_fastpath_input", ExactSpelling = true)]
public static unsafe extern SessionFfiResultBoxActiveStageOutputIteratorBoxIronRdpError ProcessFastpathInput(ActiveStage* self, DecodedImage* image, FastPathInputEventIterator* fastpathInput);
[DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStage_initiate_clipboard_copy", ExactSpelling = true)]
public static unsafe extern SessionFfiResultBoxVecU8BoxIronRdpError InitiateClipboardCopy(ActiveStage* self, ClipboardFormatIterator* formats);
[DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStage_initiate_clipboard_paste", ExactSpelling = true)]
public static unsafe extern SessionFfiResultBoxVecU8BoxIronRdpError InitiateClipboardPaste(ActiveStage* self, ClipboardFormatId* formatId);
[DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStage_submit_clipboard_format_data", ExactSpelling = true)]
public static unsafe extern SessionFfiResultBoxVecU8BoxIronRdpError SubmitClipboardFormatData(ActiveStage* self, FormatDataResponse* formatDataResponse);
[DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ActiveStage_destroy", ExactSpelling = true)]
public static unsafe extern void Destroy(ActiveStage* self);
}
@@ -55,6 +55,9 @@ public partial struct ClientConnector
[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_attach_static_cliprdr", ExactSpelling = true)]
public static unsafe extern ConnectorFfiResultVoidBoxIronRdpError AttachStaticCliprdr(ClientConnector* self, Cliprdr* cliprdr);
[DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClientConnector_next_pdu_hint", ExactSpelling = true)]
public static unsafe extern ConnectorFfiResultOptBoxPduHintBoxIronRdpError NextPduHint(ClientConnector* self);
@@ -0,0 +1,21 @@
// <auto-generated/> 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 ClipboardFormatId
{
private const string NativeLib = "DevolutionsIronRdp";
[DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClipboardFormatId_destroy", ExactSpelling = true)]
public static unsafe extern void Destroy(ClipboardFormatId* self);
}
@@ -0,0 +1,21 @@
// <auto-generated/> 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 ClipboardFormatIterator
{
private const string NativeLib = "DevolutionsIronRdp";
[DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClipboardFormatIterator_destroy", ExactSpelling = true)]
public static unsafe extern void Destroy(ClipboardFormatIterator* self);
}

Some files were not shown because too many files have changed in this diff Show More